XSLT基于子元素属性的父元素排序

时间:2015-11-28 16:33:51

标签: xml sorting xslt

虽然此问题已multiples times here here和{{3}}之前已被问过,但答案似乎都适用于该特定问题,但我无法在我的情况下工作。

这个xml

 <root>
  <Orders>
    <Order type="S">
      <Ref>ABC123</Ref>
      <OrderedBy>
        <Debtor code="13456"></Debtor>
      </OrderedBy>
      <DeliveryMethod code="Truck"></DeliveryMethod>
      <OrderLine line="1">
        <Item code="ABC100400"></Item>
        <Quantity>1</Quantity>
      </OrderLine>
      <OrderLine line="2">
        <Item code="XYZ490204" type="S" searchcode="XYZ490204"></Item>
        <Quantity>2</Quantity>
      </OrderLine>
      <OrderLine line="3">
        <Item code="DEF1210847" type="S" searchcode="DEF1210847"></Item>
        <Quantity>4</Quantity>
      </OrderLine>
    </Order>
    <Order type="S">
      <Ref>ABC123</Ref>
      <OrderedBy>
        <Debtor code="BLABLA" number="802416" type="C"></Debtor>
      </OrderedBy>
      <DeliveryMethod code="Barefoot"></DeliveryMethod>
      <OrderLine line="1">
        <Item code="QQQ123456" type="S" searchcode="QQQ123456"></Item>
        <Quantity>1</Quantity>
      </OrderLine>
      <OrderLine line="2">
        <Item code="JJJ490204" type="S" searchcode="JJJ490204"></Item>
        <Quantity>3</Quantity>
      </OrderLine>
    </Order>
  </Orders>
</root>

需要转换为这个xml:

 <root>
      <Orders>
        <Order type="S">
          <Ref>ABC123</Ref>
          <OrderedBy>
            <Debtor code="13456"></Debtor>
          </OrderedBy>
          <DeliveryMethod code="Truck"></DeliveryMethod>
          <OrderLine line="1">
             <Item code="ABC100400"></Item>
            <Quantity>1</Quantity>
          </OrderLine>
          <OrderLine line="3">
            <Item code="DEF1210847"></Item>
            <Quantity>4</Quantity>
          </OrderLine>
          <OrderLine line="2">
            <Item code="XYZ490204"></Item>
            <Quantity>2</Quantity>
          </OrderLine>
        </Order>
        <Order type="S">
          <Ref>ABC123</Ref>
          <OrderedBy>
            <Debtor code="BLABLA"></Debtor>
          </OrderedBy>
          <DeliveryMethod code="Barefoot"></DeliveryMethod>
          <OrderLine line="2">
            <Item code="JJJ490204"></Item>
            <Quantity>3</Quantity>
          </OrderLine>
          <OrderLine line="1">
            <Item code="QQQ123456"></Item>
            <Quantity>1</Quantity>
          </OrderLine>
         </Order>
      </Orders>
    </root>

我要做的是,每个<Order>根据子<OrderLine>的属性值对<Item>/@code个元素进行排序,并删除该子元素的某些属性。 OrderLine之外的所有其他元素都需要保持不变。请不要介意xml的非最佳结构,这不能改变。它可能需要复制,因为每个结合排序,像这样,但更好:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

    <xsl:template match="Orders">
        <xsl:copy>
            <xsl:apply-templates select="Order/OrderLine/Item|@*">
                <xsl:sort select="@code" data-type="text"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:4)

  

我尝试做的是<Order>对每个<OrderLine>排序<Item>/@code   基于子OrderLine ...

的属性值的元素

如果要对Order元素进行排序,则必须从其父<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"/> <xsl:strip-space elements="*"/> <!-- identity transform --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="Order"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:apply-templates select="*[not(self::OrderLine)]"/> <xsl:apply-templates select="OrderLine"> <xsl:sort select="Item/@code" data-type="text" order="ascending"/> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet> 的上下文中进行排序:

XSLT 1.0

<xsl:template match="Order">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:sort select="Item/@code" data-type="text" order="ascending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

注意:由于空字符串排序优先,您可以将模板缩短为:

Item
  

..并且还剥离了那个孩子的一些属性。

我在样式表中没有看到这一点。无论如何,只需添加另一个模板来匹配let rec find a x n = if a.(n) = x then n else find a x (n+1);; find a x 0;;