如何根据条件连接多个XML元素

时间:2018-01-26 19:25:28

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

我的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中实现这一目标?

2 个答案:

答案 0 :(得分:0)

对于您的特定目标,您可以使用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>

答案 1 :(得分:-1)

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

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

    • 复制自己的开场代码(<xsl:copy>),
    • 复制自己的内容(您甚至不需要apply-templates 对于它的孩子,普通copy会更快,
    • 仅复制兄弟PIX元素中的PIXTransactions元素 包含PIXTransactionType = 603|02
    • 复制自己的结束标记(</xsl:copy>)。
  2. 创建另一个匹配PIXTransactions的模板 PIXTransactionType = 603|02,内容为空,以阻止其内容 处理

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

  4. 所以整个脚本可能如下所示:

    <?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