如何使用xslt从文档中减少排序?

时间:2012-02-20 11:35:48

标签: xml xslt xpath

以下是document_1.xml

<products>
    <product>
        <name>Pen</name>
        <Quantity>10</Quantity>
    </product>
    <product>
        <name>Pencil</name>
        <Quantity>20</Quantity>
    </product>
    <product>
        <name>Bag</name>
        <Quantity>25</Quantity>
    </product>
</products>

document_2.xml

<products>
    <product>
        <name>Pen</name>
        <Quantity>30</Quantity>
    </product> 

    <product>
        <name>Pencil</name>
        <Quantity>5</Quantity>
    </product>
    <product>
        <name>Bag</name>
        <Quantity>2</Quantity>
    </product>
</products>

document.xml

<products>
</products>

以下是我的xsl,我曾经加入document_1.xmldocument_2.xml加入document.xml

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

<xsl:template match="/products">
<xsl:copy>
<xsl:apply-templates select="document('document_1.xml')/*/product"/>
<xsl:apply-templates select="document('document_2.xml')/*/product"/>
</xsl:copy>
</xsl:template>

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

</xsl:stylesheet>

我需要输出如下

  1. 按数量ASC排序
  2. 以最小的数量区分<name>

    <products>
        <product>
            <name>Bag</name>
            <Quantity>2</Quantity>
        </product>
        <product>
            <name>Pencil</name>
            <Quantity>5</Quantity>
        </product>
        <product>
            <name>Pen</name>
            <Quantity>10</Quantity>
        </product>
    

3 个答案:

答案 0 :(得分:0)

使用此代码进行排序

<xsl:for-each select="products/product">
      <xsl:sort select="Quantity"/>
      <tr>
        <td><xsl:value-of select="name"/></td>
        <td><xsl:value-of select="Quantity"/></td>
      </tr>
    </xsl:for-each>

答案 1 :(得分:0)

以下是一个使用大多数处理器支持的exsl:node-set扩展函数的XSLT 1.0示例:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="exsl">

  <xsl:param name="doc1-url" select="'document1.xml'"/>
  <xsl:param name="doc2-url" select="'document2.xml'"/>

  <xsl:variable name="doc1" select="document($doc1-url)"/>
  <xsl:variable name="doc2" select="document($doc2-url)"/>

  <xsl:output indent="yes"/>

  <xsl:key name="k1" match="product" use="name"/>

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

  <xsl:template match="products">
    <xsl:copy>
      <xsl:variable name="joined-products">
        <xsl:copy-of select="$doc1//product | $doc2//product"/>
      </xsl:variable>
      <xsl:variable name="grouped-products">
        <xsl:apply-templates select="exsl:node-set($joined-products)/product[generate-id() = generate-id(key('k1', name)[1])]" mode="group"/>
      </xsl:variable>
      <xsl:apply-templates select="exsl:node-set($grouped-products)/product">
        <xsl:sort select="Quantity" data-type="number"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="product" mode="group">
    <xsl:copy>
      <xsl:copy-of select="name"/>
      <Quantity>
        <xsl:for-each select="key('k1', name)">
          <xsl:sort select="Quantity" data-type="number"/>
          <xsl:if test="position() = 1">
            <xsl:value-of select="Quantity"/>
          </xsl:if>
        </xsl:for-each>
      </Quantity>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

这个简单的转型

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kProdByName" match="product" use="name"/>

<xsl:variable name="vallProds" select=
 "document('file:///c:/temp/delete/document_1.xml')/*/*
 |
  document('file:///c:/temp/delete/document_2.xml')/*/*
 "/>

 <xsl:template match="/*">
    <xsl:variable name="vrtfProds">
   <xsl:apply-templates select="$vallProds">
    <xsl:sort select="name"/>
    <xsl:sort select="Quantity" data-type="number"/>
   </xsl:apply-templates>
  </xsl:variable>

  <products>
   <xsl:for-each select="msxsl:node-set($vrtfProds)">
    <xsl:copy-of select=
     "*[generate-id() = generate-id(key('kProdByName', name)[1])]"/>
   </xsl:for-each>
  </products>
 </xsl:template>

 <xsl:template match="product">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

应用于任何XML文档(可能是document.xml,但未使用),并且提供了两个提供的文档:c:\temp\delete\document_1.xmlc:\temp\delete\document_1.xml

生成想要的正确结果

<products>
    <product>
        <name>Bag</name>
        <Quantity>2</Quantity>
    </product>
    <product>
        <name>Pen</name>
        <Quantity>10</Quantity>
    </product>
    <product>
        <name>Pencil</name>
        <Quantity>5</Quantity>
    </product>
</products>

<强>解释

  1. 使用两个键排序两个文档的联合的product元素name Quantity

  2. 从上面步骤1中生成的RTF( Result Tree Fragment )中提取常规树,并执行{{Muenchian grouping {{ 1}} product