XSLT - 与兄弟帖子排序比较

时间:2016-12-05 19:29:39

标签: xml sorting xslt xpath

我有以下想要排序的xml结构

<ESTABLISHMENTS>
    <ESTABLISHMENT>
        <NAME>A</NAME>
        <LOCATION>
            <LOCALITY>A</LOCALITY>
        </LOCATION>
        <RATING>
            <LEVEL>1</LEVEL>
            <SCORE>50</SCORE>
        </RATING>
    </ESTABLISHMENT>
    <ESTABLISHMENT>
        <NAME>C</NAME>
        <LOCATION>
            <LOCALITY>B</LOCALITY>
        </LOCATION>
        <RATING>
            <LEVEL>2</LEVEL>
            <SCORE>50</SCORE>
        </RATING>
    </ESTABLISHMENT>
    <ESTABLISHMENT>
        <NAME>B</NAME>
        <LOCATION>
            <LOCALITY>B</LOCALITY>
        </LOCATION>
        <RATING>
            <LEVEL>2</LEVEL>
            <SCORE>50</SCORE>
        </RATING>
    </ESTABLISHMENT>
</ESTABLISHMENTS>

我的目标是先按地点排序,然后按评级,然后按评分,最后按名称排序。 我已设法使用以下代码

进行排序
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" omit-xml-declaration="no"/>
    <xsl:key name="establishment-by-locality" match="ESTABLISHMENTS/ESTABLISHMENT/LOCATION"
        use="LOCALITY"/>
    <xsl:template match="EXPORT">
    <xsl:for-each select="ESTABLISHMENTS/ESTABLISHMENT/LOCATION[count(.| key('establishment-by-locality', LOCALITY)[1]) = 1]">
         <xsl:sort select="LOCALITY"/>
         <xsl:for-each select="key('establishment-by-locality', LOCALITY)">
                 <xsl:sort select="../RATING/LEVEL" data-type="number" order="descending"/>
                 <xsl:sort select="../RATING/MERIT_SCORE" data-type="number" order="descending"/>
                 <xsl:sort select="../NAME"/>

                 <xsl:apply-templates select="ancestor::ESTABLISHMENT" mode="test"/>
          </xsl:for-each>
     </xsl:for-each>
     </xsl:template>
     <xsl:template match="node()" mode="test">       
          <hotel>    
          <name>
            <xsl:value-of select="NAME"/>
          </name>
          <town>
            <xsl:value-of select="LOCATION/LOCALITY"/>
          </town>
          <level>
            <xsl:value-of select="RATING/LEVEL"/>
          </level>
          <score>
            <xsl:value-of select="RATING/MERIT_SCORE"/>
        </score>
    </hotel>
</xsl:template></xsl:stylesheet>

但是,一旦对XML进行了排序,我想将“LOCALITY”值与新的进程建立进行比较,但仍受到仍使用原始树的XPath的限制。不幸的是,我被限制在XSLT 1.0,因为目的地是Adobe InDesign。

非常感谢任何帮助。

修改

比较的目的是决定是否插入和附加元素,即如果地点不同则添加节标题。

最终所需的输出是以下几行

<establishments>
    <town>
        <townName>A</townName>
        <hotel>
            <name>A</name>
            <town>A</town>
            <level>1</level>
            <score>50</score>
        </hotel>
    </town>
    <town>
        <townName>B</townName>
        <hotel>
            <name>B</name>
            <town>B</town>
            <level>2</level>
            <score>50</score>
        </hotel>
        <hotel>
            <name>C</name>
            <town>B</town>
            <level>2</level>
            <score>50</score>
        </hotel>
    </town>
</establishments> 

1 个答案:

答案 0 :(得分:1)

我看到没有必要进行这样的比较。通过将以下样式表应用于示例输入,可以轻松获得预期输出:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="establishment-by-locality" match="ESTABLISHMENT" use="LOCATION/LOCALITY"/>

<xsl:template match="/ESTABLISHMENTS">
    <establishments>
        <xsl:for-each select="ESTABLISHMENT[count(.| key('establishment-by-locality', LOCATION/LOCALITY)[1]) = 1]">
            <xsl:sort select="LOCATION/LOCALITY"/>
            <town>
                <townName>
                    <xsl:value-of select="LOCATION/LOCALITY"/>
                </townName>
                <xsl:apply-templates select="key('establishment-by-locality', LOCATION/LOCALITY)">
                    <xsl:sort select="RATING/LEVEL" data-type="number" order="descending"/>
                    <xsl:sort select="RATING/SCORE" data-type="number" order="descending"/>
                    <xsl:sort select="NAME"/>
                </xsl:apply-templates>
            </town>
        </xsl:for-each>
    </establishments>
</xsl:template>

<xsl:template match="ESTABLISHMENT">       
    <hotel>    
        <name>
            <xsl:value-of select="NAME"/>
        </name>
        <town>
            <xsl:value-of select="LOCATION/LOCALITY"/>
        </town>
        <level>
            <xsl:value-of select="RATING/LEVEL"/>
        </level>
        <score>
            <xsl:value-of select="RATING/SCORE"/>
        </score>
    </hotel>
</xsl:template>

</xsl:stylesheet>

注意:显然您的实际输入结构略有不同。你必须自己做出调整。