我有一个输入XML文件,我需要将1:1复制到输出中,除了一个包含需要排序的子项的子元素。
<?xml version="1.0"?>
<top>
<elementA />
<elementB />
<contents>
<contentitem>
<id>3</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>2</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>1</id>
<moretags1 />
<moretags2 />
</contentitem>
</contents>
</top>
我想要一个XSL Transformation,它将“contentitem”元素按顺序排列,按其“id”元素排序。 必须逐字复制所有其他标记,包括嵌套标记。我已经尝试过使用xsl:copy,但要么我得到了双重内容,要么结果丢失了。
答案 0 :(得分:7)
Mark Gravell的解决方案几乎是正确的 - 稍有问题会产生两个嵌套的<contents>
元素。 请注意所有提供答案的人:测试您的解决方案!
这是一个正确的解决方案。这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!-- -->
<xsl:strip-space elements="*"/>
<!-- -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="contents">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="contentitem">
<xsl:sort select="id" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于最初提供的XML文档:
<top>
<elementA />
<elementB />
<contents>
<contentitem>
<id>3</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>2</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>1</id>
<moretags1 />
<moretags2 />
</contentitem>
</contents>
</top>
生成想要的正确结果:
<top>
<elementA/>
<elementB/>
<contents>
<contentitem>
<id>1</id>
<moretags1/>
<moretags2/>
</contentitem>
<contentitem>
<id>2</id>
<moretags1/>
<moretags2/>
</contentitem>
<contentitem>
<id>3</id>
<moretags1/>
<moretags2/>
</contentitem>
</contents>
</top>
请注意以下:
使用identity rule 复制所有节点而不做任何更改。
如何使用与contents
元素匹配的特定模板覆盖身份模板
使用<xsl:sort>
指令来显示以特定顺序应用模板的结果,可能与选择进行处理的节点的文档顺序不同。
答案 1 :(得分:2)
怎么样:
<?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" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/top/contents">
<contents>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="contentitem">
<xsl:sort data-type="number" select="id"/>
</xsl:apply-templates>
</xsl:copy>
</contents>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
使用xsl:sort与xsl:for-each或xsl:apply-templates
像
这样的东西<xsl:template match='/top/contents'>
<xsl:apply-templates select='contentitem'>
<xsl:sort select='id' data-type='number'/>
</xsl:apply-templates>
</xsl:template>
多个xsl:sort元素可用于多个排序键。