2

我有一个非常不寻常的场景。以前从未听说过或做过这样的事情。这是我的源 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 转换中做到这一点吗?

4

2 回答 2

4

是的,有可能。将模板应用于 List 元素时,使用具有属性 order="descending" 的 <xsl:sort> 元素。

<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>

编辑:我忘了在排序元素中包含 select="position()" data-type="number" 属性

再次编辑以回答您的其他要求:已替换(如丹尼尔已指出)

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

这样

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

或者,如果您愿意,可以使用它。注意最后一个空模板,它抑制了除子名称之外的任何列表的孩子

<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>
于 2013-08-21T11:30:16.443 回答
1

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

<?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>

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

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

于 2013-08-21T11:24:01.667 回答