XSL使用计数器撤消订单

时间:2013-08-21 10:58:42

标签: xml xslt transformation

我有一个非常不寻常的场景。从来没有听过或做过这样的事情。这是我的源XML。

<?xml version="1.0" encoding="UTF-8"?>
<ListItems>
   <List>
     <name>A</name>
   </List>
   <List>
     <name>B</name>
   </List>
   <List>
     <name>C</name>
   </List>
   <List>
     <name>D</name>
   </List>
</ListItems>

我要做的是用反向计数器作为索引来反转列表的顺序。生成的XML应如下所示:

<UpdateListItems>
   <List>
     <name>D</name>
     <index>4</index>
   </List>
   <List>
     <name>C</name>
     <index>3</index>
   </List>
   <List>
     <name>B</name>
     <index>2</index>
   </List>
   <List>
     <name>A</name>
     <index>1</index>
   </List>
</UpdateListItems>

请注意反向顺序的名称,并以相反的顺序添加索引。听起来有点愚蠢但是有可能在xml转换中做到这一点吗?

2 个答案:

答案 0 :(得分:4)

是的,可能。使用&lt; xsl:sort&gt;将模板应用于List元素时,具有属性order =“descending”的元素。

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

    <xsl:template match = "/ListItems" >
        <xsl:copy>
            <xsl:apply-templates select = "List" >
                <xsl:sort order="descending" select="position()" data-type="number"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match = "node()|@*" >
        <xsl:copy>
          <xsl:apply-templates select = "node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match = "List" >
        <xsl:copy>
            <xsl:apply-templates select = "name"/>
            <index><xsl:value-of select="1 + last() - position()"/></index>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

编辑:我忘了在sort元素中包含select =“position()”data-type =“number”属性

再次编辑以回答您的其他要求: 取代(正如丹尼尔已经指出的那样)

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

由此

<xsl:apply-templates select = "name"/>

或者如果您愿意,可以使用它。注意最后一个空模板,它禁止除子名称之外的任何List子项

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

    <xsl:template match = "/ListItems" >
        <xsl:copy>
            <xsl:apply-templates select = "List" >
                <xsl:sort order="descending" select="position()" data-type="number"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match = "node()|@*" >
        <xsl:copy>
          <xsl:apply-templates select = "node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match = "List" >
        <xsl:copy>
            <xsl:apply-templates select = "node()|@*"/>
            <index><xsl:value-of select="1 + last() - position()"/></index>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="List/*[not(self::name)]"/>
</xsl:stylesheet>

答案 1 :(得分:1)

在xsl中,您可以根据位置按降序对List进行排序。

<?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
<xsl:template match="/">
<UpdatedListItems>
<xsl:for-each select="/ListItems/List/name">
<xsl:sort select="position()" data-type="number" order="descending"/>
<List>
<name><xsl:value-of select="."/></name>
</List>
</xsl:for-each>
</UpdatedListItems>
</xsl:template>
</xsl:stylesheet>

在更正后的输入(更改<name/> to </name>)上通过xsltproc运行此操作会产生以下结果:

  

<UpdatedListItems><List><name>D</name></List><List><name>C</name></List><List><name>B</name></List><List><name>A</name></List></UpdatedListItems>