2011-04-27 57 views
2

我想使用模板来反转不同的XML序列; 例如:孩子的扭转顺序

<book title="Definitive XML Schema"> 
    <author first="Priscilla" /> 
    <chapter title="[I] "> 
    <section title="[I.1]" /> 
    <section title="[I.2]"> 
     <section title="[I.2.1]" /> 
     <section title="[I.2.2]" /> 
    </section> 
    <section title="[I.3] "> 
     <section title="[I.3.1]" /> 
    </section> 
    </chapter> 
    <chapter title="[II]"> 
    <section title="[II.1]" /> 
    <section title="[II.2]"> 
     <section title="[II.2.1]" /> 
     <section title="[II.2.2]" /> 
    </section> 
    </chapter> 
</book> 

我想要得到这样的输出:这是我的XSL。

<?xml version="1.0" encoding="UTF-8"?> 
<book title="Definitive XML Schema"> 
    <author first="Priscilla"/> 
    <chapter title="[I]"> 
     <section title="[I.3]"> 
     <section title="[I.3.1]"/> 
     </section> 
     <section title="[I.2]"> 
     <section title="[I.2.2]"/> 
     <section title="[I.2.1]"/> 
     </section> 
     <section title="[I.1]"/> 
    </chapter> 
    <chapter title="[II]"> 
     <section title="[II.2]"> 
     <section title="[II.2.2]"/> 
     <section title="[II.2.1]"/> 
     </section> 
     <section title="[II.1]"/> 
    </chapter> 
</book> 

是的,这些部分已被颠倒,但章节没有。

我尝试使用两个模板来解决它,但它不能工作..

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:transform version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent ="yes"/> 
<xsl:template match="/"> 
<xsl:apply-templates/> 
<xsl:text>&#10;</xsl:text> 
</xsl:template> 

<xsl:template match="book"> 
    <xsl:copy> 
    <xsl:sequence select="@title"/> 
    <xsl:sequence select="author"/> 
    <xsl:apply-templates select="chapter"> 
    <xsl:with-param name="seq" select="section"/> 

    </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

<xsl:template match ="chapter|section" as="element()"> 
    <xsl:param name="seq" as="element(section)*"/> 
    <xsl:copy> 
    <xsl:sequence select="@title"/> 
    <xsl:if test="not(empty($seq))"> 
    <xsl:apply-templates select="chapter"> 
     <xsl:with-param name="seq" select="$seq[position()>1]"/> 
    </xsl:apply-templates> 
    <xsl:apply-templates select="$seq[1]"/>  
    </xsl:if> 
    </xsl:copy> 
</xsl:template> 
</xsl:transform> 
+0

我没有看到第一个和第二个XML之间的任何区别。但是,如果你想多次使用一些不同的模板 - 阅读模板中的“模式”属性(http://msdn.microsoft.com/en-us/library/ms256110.aspx) – TOUDIdel 2011-04-27 06:00:34

+0

好问题,+1。请参阅我的答案,了解目前呈现的完整且最简单/最短的解决方案。 :) – 2011-04-28 02:47:20

回答

1

这是一个更简单的XSLT 1.0(和2.0)解决方案

<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="*[section]"> 
    <xsl:copy> 
    <xsl:copy-of select="@*"/> 
    <xsl:apply-templates> 
    <xsl:sort select="position()" 
     data-type="number" order="descending"/> 
    </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

当该变换被应用在下面的XML文档:产生

<book title="Definitive XML Schema"> 
    <author first="Priscilla" /> 
    <chapter title="[I] "> 
    <section title="[I.1]" /> 
    <section title="[I.2]"> 
     <section title="[I.2.1]" /> 
     <section title="[I.2.2]" /> 
    </section> 
    <section title="[I.3] "> 
     <section title="[I.3.1]" /> 
    </section> 
    </chapter> 
    <chapter title="[II]"> 
    <section title="[II.1]" /> 
    <section title="[II.2]"> 
     <section title="[II.2.1]" /> 
     <section title="[II.2.2]" /> 
    </section> 
    </chapter> 
</book> 

有用,正确的结果(翻转section元素的所有序列):

<book title="Definitive XML Schema"> 
    <author first="Priscilla"/> 
    <chapter title="[I] "> 
     <section title="[I.3] "> 
     <section title="[I.3.1]"/> 
     </section> 
     <section title="[I.2]"> 
     <section title="[I.2.2]"/> 
     <section title="[I.2.1]"/> 
     </section> 
     <section title="[I.1]"/> 
    </chapter> 
    <chapter title="[II]"> 
     <section title="[II.2]"> 
     <section title="[II.2.2]"/> 
     <section title="[II.2.1]"/> 
     </section> 
     <section title="[II.1]"/> 
    </chapter> 
</book> 
+0

@Dimitre Novatchev:谢谢你的好回答,如果我不想使用元素,并且想要使用,那我该怎么办? – ZAWD 2011-04-28 11:15:01

+0

@ZAWD:''的设计目的是当每个节点的处理结果的期望顺序不是默认值时,呈现应用模板(和')的结果的目的文件)命令。如果由于某种无法解释的原因,您不想使用'',那么理论上您可以始终处理最后一个元素,然后在部分结果上应用模板。当然,这是非常不合适的。 – 2011-04-28 12:28:30

+0

@Dimitre Novatchev:是的,我试图用这种方法制作它。创建一个模板并调用它,但它是一个很长的故事,我想使它更短,但没有 .. :) 1]“/>

ZAWD 2011-04-28 13:40:12

1

这XSLT 2.0样式表:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="node()|@*" name="identity"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="chapter|section"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:apply-templates> 
       <xsl:sort select="tokenize(@title,'.')[last()]" 
          order="descending" 
          data-type="number"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

输出:

<book title="Definitive XML Schema"> 
    <author first="Priscilla"/> 
    <chapter title="[I] "> 
     <section title="[I.3] "> 
      <section title="[I.3.1]"/></section> 
     <section title="[I.2]"> 
      <section title="[I.2.2]"/> 
      <section title="[I.2.1]"/></section> 
     <section title="[I.1]"/> 
    </chapter> 
    <chapter title="[II]"> 
     <section title="[II.2]"> 
      <section title="[II.2.2]"/> 
      <section title="[II.2.1]"/></section> 
     <section title="[II.1]"/> 
    </chapter> 
</book> 
+0

@Alejandro:为什么这样一个不必要的复杂解决方案? – 2011-04-28 02:49:43

+0

@Alejandro:谢谢你的回答,但我认为这些部分不会颠倒...... – ZAWD 2011-04-28 11:12:08

+0

@ZAWD:你应该看两次;) – 2011-04-28 13:06:01