在节点上拆分XML并插入常规信息

时间:2018-06-04 11:49:41

标签: xml xslt-2.0

客户可以提供具有以下结构的整合XML:

<invoices>
<invoice>
    <order_id>
        <ordernumber>1000</ordernumber>
    </order_id>
    <general_info/>
    <address/>
    <product>
        <id>A</id>
        <item/>
        <item/>
    </product>
    <product>
        <id>B</id>
        <item/>
        <item/>
    </product>
    <product>
        <id>C</id>
        <item/>
        <item/>
    </product>
</invoice>
<invoice>
    <order_id>
        <ordernumber>2000</ordernumber>
    </order_id>
    <general_info/>
    <address/>
    <product>
        <id>D</id>
        <item/>
        <item/>
    </product>
</invoice>
</invoices>

根元素&#34;发票&#34;可以包含&#34; invoice&#34;的多个实例(订单本身,在这种情况下2个订单) 然而&#34;发票&#34;也可以包含&#34; product&#34;的多个实例。 (订单行,order_id 1000的3个订单行和order_id 2000的1个订单行)

我们需要的是每个订单行的XML,其中包含一个&#34;产品&#34;和&#34;发票&#34;使用order_id,常规信息和addrress始终存在。

<invoices>
<invoice>
    <order_id>
        <ordernumber>1000</ordernumber>
    </order_id>
    <product>
        <general_info/>
        <address/>
        <id>A</id>
        <item/>
        <item/>
    </product>
</invoice>
<invoice>
    <order_id>
        <ordernumber>1000</ordernumber>
    </order_id>
    <product>
        <general_info/>
        <address/>
        <id>B</id>
        <item/>
        <item/>
    </product>
</invoice>
<invoice>
    <order_id>
        <ordernumber>1000</ordernumber>
    </order_id>
    <product>
        <general_info/>
        <address/>
        <id>C</id>
        <item/>
        <item/>
    </product>
</invoice>
<invoice>
    <order_id>
        <ordernumber>2000</ordernumber>
    </order_id>
    <general_info/>
    <address/>
    <product>
        <id>D</id>
        <item/>
        <item/>
    </product>
</invoice>
</invoices>

我们一直在研究这样的多重拆分方案: 1.在发票上拆分以获得单独的订单 2.将单独的订单拆分为订单行并转换(XSL)分离的XML以包含order_id,常规信息和地址。

拆分1(在&#34;发票&#34;)没有问题(虽然在外部程序的帮助下)。

我们能够完全开始工作的工作是分开并保留一般信息。 Sofar我们尝试使用模板匹配和for-each语句对XML进行转换,但无法使其正常工作。

如果有人知道如何做到这一点?

2 个答案:

答案 0 :(得分:0)

直接表示
  <xsl:template match="invoices">
    <xsl:copy>
        <xsl:apply-templates select="invoice/product"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="product">
      <invoice>
          <xsl:copy-of select="../order_id"/>
          <xsl:copy>
              <xsl:copy-of select="../general-info, ../address, *"/>
          </xsl:copy>
      </invoice>
  </xsl:template>

完整样本

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="invoices">
    <xsl:copy>
        <xsl:apply-templates select="invoice/product"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="product">
      <invoice>
          <xsl:copy-of select="../order_id"/>
          <xsl:copy>
              <xsl:copy-of select="../general-info, ../address, *"/>
          </xsl:copy>
      </invoice>
  </xsl:template>

</xsl:stylesheet>

在线https://xsltfiddle.liberty-development.net/3NzcBt3

答案 1 :(得分:0)

感谢Martin,这确实适用于XML示例。 只是注意到在生产XML中,节点“product”实际上是低一级(父节点“products”)。

<invoices>
<invoice>
    <order_id>
        <ordernumber>1000</ordernumber>
    </order_id>
    <general_info>General A</general_info>
    <address>Adres A</address>
    <products>
        <product>
            <id>A</id>
            <item/>
            <item/>
        </product>
        <product>
            <id>B</id>
            <item/>
            <item/>
        </product>
        <product>
            <id>C</id>
            <item/>
            <item/>
        </product>
    </products>
</invoice>
<invoice>
    <order_id>
        <ordernumber>2000</ordernumber>
    </order_id>
    <general_info>General B</general_info>
    <address>Adres B</address>
    <products>
        <product>
            <id>D</id>
            <item/>
            <item/>
        </product>
    </products>
</invoice>
</invoices>

我已经调整了apply-templates以反映这一点,但是有一些问题需要让XSLT的后半部分工作(模板匹配=“产品”)

XSLT

<xsl:template match="invoices">
    <xsl:copy>
        <xsl:apply-templates select="invoice/products/product"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="product">
    <invoice>
        <xsl:copy-of select="../order_id"/>
        <xsl:copy>
            <xsl:copy-of select="../general_info, ../address, *"/>
        </xsl:copy>
    </invoice>
</xsl:template>
</xsl:stylesheet>

输出包含“item”的数据,但缺少“order_id”,“general_info”和“address”。 我认为这是因为“产品”的水平,而且这与“../xxxxxx”不再匹配了?