【问题标题】:How to join multiple XML elements based on condition如何根据条件连接多个 XML 元素
【发布时间】:2018-01-26 19:25:27
【问题描述】:

我有以下结构的 XML 文件。每个 PIX 事务都有多个 PIX 消息。它们根据交易类型进行分组。我需要加入两个特定 PIXTransactionTypes = 613|05 和 603|02 的 PIX 消息。

<Message>
    <PIXTransactions>
        <PIXTransactionType>613|05</PIXTransactionType>
        <PIX>
            <Name>A</Name>
        </PIX>
    </PIXTransactions>
    <PIXTransactions>
        <PIXTransactionType>603|02</PIXTransactionType>
        <PIX>
            <Name>B</Name>
        </PIX>
        <PIX>
            <Name>C</Name>
        </PIX>
        <PIX>
            <Name>D</Name>
        </PIX>
    </PIXTransactions>
    <PIXTransactions>
        <PIXTransactionType>602|02</PIXTransactionType>
        <PIX>
            <Name>F</Name>
        </PIX>
        <PIX>
            <Name>G</Name>
        </PIX>
        <PIX>
            <Name>G</Name>
        </PIX>
    </PIXTransactions>
</Message>

我生成的 XML 应该是

<Message>
    <PIXTransactions>
        <PIXTransactionType>613|05</PIXTransactionType>
        <PIX>
            <Name>A</Name>
        </PIX>
        <PIX>
            <Name>B</Name>
        </PIX>
        <PIX>
            <Name>C</Name>
        </PIX>
        <PIX>
            <Name>D</Name>
        </PIX>
    </PIXTransactions>
    <PIXTransactions>
        <PIXTransactionType>602|02</PIXTransactionType>
        <PIX>
            <Name>F</Name>
        </PIX>
        <PIX>
            <Name>G</Name>
        </PIX>
        <PIX>
            <Name>G</Name>
        </PIX>
    </PIXTransactions>
</Message>

如何在 XSLT 1.0 或 2.0 中实现这一点?

【问题讨论】:

  • 为什么&lt;PIXTransactionType&gt;603|02&lt;/PIXTransactionType&gt;的输入中的PIX元素在输出中映射到&lt;PIXTransactionType&gt;613|05&lt;/PIXTransactionType&gt;

标签: xml xslt xslt-1.0 xslt-2.0 soa


【解决方案1】:

对于您的特定目标,您可以使用 copy-of 和预定义参数为 param.pix.fromparam.pix.to,如下面的 XSL 中所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>
    <!--define parameters FROM and TO-->
    <xsl:param name="param.pix.from" select="'603|02'" />
    <xsl:param name="param.pix.to" select="'613|05'" />
    <!--copy required PIXs to matched PIXTransactions block-->    
    <xsl:template match="PIXTransactions[PIXTransactionType = $param.pix.to]">
        <xsl:element name="{name()}">
            <xsl:copy-of select="*"/>                
            <xsl:copy-of select="/Message/PIXTransactions[PIXTransactionType = $param.pix.from]/*[name() = 'PIX']"/>
        </xsl:element>
    </xsl:template>
    <!--exclude required PIXTransactions from where PIXs blocks were taken-->
    <xsl:template match="PIXTransactions[PIXTransactionType = $param.pix.from]"/>
    <!--copy all nodes and attributes-->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>    
</xsl:stylesheet>

结果如预期:

<?xml version="1.0" encoding="UTF-8"?>
<Message>
    <PIXTransactions>
        <PIXTransactionType>613|05</PIXTransactionType>
        <PIX>
            <Name>A</Name>
        </PIX>
        <PIX>
            <Name>B</Name>
        </PIX>
        <PIX>
            <Name>C</Name>
        </PIX>
        <PIX>
            <Name>D</Name>
        </PIX>
    </PIXTransactions>

    <PIXTransactions>
        <PIXTransactionType>602|02</PIXTransactionType>
        <PIX>
            <Name>F</Name>
        </PIX>
        <PIX>
            <Name>G</Name>
        </PIX>
        <PIX>
            <Name>G</Name>
        </PIX>
    </PIXTransactions>
</Message>

【讨论】:

    【解决方案2】:

    假设Message 元素总是包含 PIXTransactions/PIXTransactionType = 613|05, 该任务可以按如下方式执行:

    1. 创建一个匹配PIXTransactions的模板,包含 PIXTransactionType = 613|05。它应该:

      • 复制自己的开始标签(&lt;xsl:copy&gt;),
      • 复制自己的内容(你甚至不需要apply-templates 对它的孩子来说,普通的copy 会更快),
      • 仅从兄弟PIXTransactions元素复制PIX元素 包含PIXTransactionType = 603|02
      • 复制自己的结束标签 (&lt;/xsl:copy&gt;)。
    2. 创建另一个匹配 PIXTransactions 的模板,包含 PIXTransactionType = 603|02,内容为空,阻止其 处理。

    3. 最后一个需要的脚本片段是身份模板

    所以整个脚本如下所示:

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" encoding="UTF-8" indent="yes" />
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="PIXTransactions[PIXTransactionType = '613|05']">
        <xsl:copy>
          <xsl:copy-of select="node()"/>
          <xsl:copy-of select="../PIXTransactions[PIXTransactionType = '603|02']/PIX"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="PIXTransactions[PIXTransactionType = '603|02']"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
      </xsl:template>
    </xsl:transform>
    

    它也适用于 XSLT 2.0

    【讨论】:

      猜你喜欢
      • 2015-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 2019-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多