【问题标题】:split a large xml using xslt 1.0使用 xslt 1.0 拆分大型 xml
【发布时间】:2014-05-16 15:45:49
【问题描述】:

我必须使用以下格式的大型 xml。

<First>
<Second Argument="12" Argument2="34" >
    <Order InvOrg="123" Identifier="3580456" >
                <SupplyDetails Type="TRACK" Quantity="7" Demand="ONHAND" />
    </Order>
    <Order InvOrg="Test" Identifier="3580457" >
                <SupplyDetails Type="TRACK" Quantity="15" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="3580458" >
                <SupplyDetails Type="TRACK" Quantity="17" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="3580459" >
                <SupplyDetails Type="TRACK" Quantity="10" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888144" >
                <SupplyDetails Type="TRACK" Quantity="3" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888147" >
                <SupplyDetails Type="TRACK" Quantity="9" Demand="ONHAND" />
    <Order>
    <Order InvOrg="123" Identifier="2749622" >
                <SupplyDetails Type="TRACK" Quantity="142" Demand="ONHAND" />
    </Order>
</Second>
</First>

我需要把它转换成下面的格式

<First>
<Second Argument="12" Argument2="34" >
    <Order InvOrg="123" Identifier="3580456" >
                <SupplyDetails Type="TRACK" Quantity="7" Demand="ONHAND" />
    </Order>
    <Order InvOrg="Test" Identifier="3580457" >
                <SupplyDetails Type="TRACK" Quantity="15" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="3580458" >
                <SupplyDetails Type="TRACK" Quantity="17" Demand="ONHAND" />
    </Order>
</Second>
</First>
<First>
<Second Argument="12" Argument2="34" >
    <Order InvOrg="123" Identifier="3580459" >
                <SupplyDetails Type="TRACK" Quantity="10" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888144" >
                <SupplyDetails Type="TRACK" Quantity="3" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888147" >
                <SupplyDetails Type="TRACK" Quantity="9" Demand="ONHAND" />
    <Order>
    <Order InvOrg="123" Identifier="2749622" >
                <SupplyDetails Type="TRACK" Quantity="142" Demand="ONHAND" />
    </Order>
</Second>
</First>

在xslt 2.0中,可以用下面的代码实现..

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


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

<xsl:template match="/First">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="Second">
  <xsl:for-each-group select="Order" group-starting-with="Order[(position() -1)mod 3 = 0]">

    <First>
       <Second>
          <xsl:copy-of select="current-group()"/>
       </Second>
    </First>

  </xsl:for-each-group>
</xsl:template>

我的项目只使用了xslt 1.0,所以我需要把上面的逻辑改成1.0。我如何在 xslt 1.0 中实现相同的逻辑

【问题讨论】:

  • 您的 XSLT 2.0 代码似乎将块组织为三个一组,这将产生 3 个块(最后一个块仅包含一个元素),但您想要的上面的结果有 2 个块(第二个带有4 个元素)。您期待这两种结果中的哪一种?
  • 另请注意,您请求的输出没有根元素。
  • @helderdarocha - 我给出的结果样本并不完美,但 xsl 是。
  • @michael.hor257k- 正确,错过了提供根节点,但 Marcus Rickert 解决方案也满足了这一要求。

标签: xml xslt-1.0


【解决方案1】:

以下 XSLT 使用递归来“迭代”顺序并拆分已配置大小(例如 3)的块。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

  <!-- set the elements per block -->
  <xsl:param name="block_length" select="3"/>

  <!-- initialize the "iteration" over the Order elements by selecting all
       of them as the "child_list" -->
  <xsl:template match="/First">
    <root>
      <xsl:call-template name="split">
        <xsl:with-param name="child_list" select="Second/Order"/>
      </xsl:call-template>
    </root>
  </xsl:template>

  <!-- handle a list of orders, split off the first three and then "iterate" over
       the remaining orders by recursion -->
  <xsl:template name="split">
    <xsl:param name="child_list"/>


    <xsl:if test="count($child_list) &gt; 0">
      <!-- split off the first three -->
      <First>
        <Second>
          <xsl:copy-of select="$child_list[position() &lt;= $block_length]"/>
        </Second>
      </First>

      <!-- handle the remaining entries by recursion -->
      <xsl:call-template name="split">
        <xsl:with-param name="child_list" select="$child_list[position() > $block_length]"/>
      </xsl:call-template>
    </xsl:if>

  </xsl:template>

</xsl:stylesheet>

产生这个结果

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <First>
    <Second>
      <Order InvOrg="123" Identifier="3580456">
        <SupplyDetails Type="TRACK" Quantity="7" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="Test" Identifier="3580457">
        <SupplyDetails Type="TRACK" Quantity="15" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="123" Identifier="3580458">
        <SupplyDetails Type="TRACK" Quantity="17" Demand="ONHAND"/>
      </Order>
    </Second>
  </First>
  <First>
    <Second>
      <Order InvOrg="123" Identifier="3580459">
        <SupplyDetails Type="TRACK" Quantity="10" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="123" Identifier="2888144">
        <SupplyDetails Type="TRACK" Quantity="3" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="123" Identifier="2888147">
        <SupplyDetails Type="TRACK" Quantity="9" Demand="ONHAND"/>
      </Order>
    </Second>
  </First>
  <First>
    <Second>
      <Order InvOrg="123" Identifier="2749622">
        <SupplyDetails Type="TRACK" Quantity="142" Demand="ONHAND"/>
      </Order>
    </Second>
  </First>
</root>

我会假设这个解决方案有一小部分复杂性 O(n*n) n 是订单的初始数量,因此您可能会遇到大量订单数量的性能问题。

【讨论】:

  • 上述逻辑完全符合我的要求。感谢您的时间和努力。
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
  • 2011-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多