1

好的,所以基于这个问题XSLT 1.0 sort elements我无法弄清楚为什么以下内容不起作用:

我有以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<viewentries>
    <viewentry>
        <entrydata name="Waste">
            <text>Bric-a-Brac</text>
        </entrydata>
        <entrydata name="Disposal">
            <text/>
        </entrydata>
    </viewentry>
    <viewentry>
        <entrydata name="Waste">
            <textlist>
                <text>Paper</text>
                <text>Glass</text>
            </textlist>
        </entrydata>
        <entrydata name="Disposal">
            <text/>
        </entrydata>
    </viewentry>
        <viewentry>
        <entrydata name="Waste">
            <textlist>
                <text>Paper</text>
                <text>Cans</text>
            </textlist>
        </entrydata>
        <entrydata name="Disposal">
                <text>Washing Machines</text>
                <text>Cars</text>
        </entrydata>
    </viewentry>
</viewentries>

以及以下 XSLT:

<?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:key name="k1" match="entrydata[@name = 'Waste' or @name = 'Disposal']//text" use="concat(ancestor::entrydata/@name, '|', .)"/>

    <xsl:template match="viewentries">
        <categories>
            <xsl:apply-templates/>
        </categories>
    </xsl:template>

    <xsl:template match="viewentry">
        <xsl:apply-templates select="entrydata[@name =  'Waste' or @name = 'Disposal']//text
      [generate-id() = generate-id(key('k1', concat(ancestor::entrydata/@name, '|', .))[1])]">
            <xsl:sort select="."/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="text[normalize-space() != '']">
        <category type="{ancestor::entrydata/@name}">
            <xsl:apply-templates/>
        </category>
    </xsl:template>

</xsl:stylesheet>

这给出了以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<categories>
    <category type="Waste">Bric-a-Brac</category>
    <category type="Waste">Glass</category>
    <category type="Waste">Paper</category>
    <category type="Waste">Cans</category>
    <category type="Disposal">Cars</category>
    <category type="Disposal">Washing Machines</category>
</categories>

我需要按排序顺序输出:

<?xml version="1.0" encoding="UTF-8"?>
<categories>
    <category type="Waste">Bric-a-Brac</category>
    <category type="Waste">Cans</category>
    <category type="Disposal">Cars</category>
    <category type="Waste">Glass</category>
    <category type="Waste">Paper</category>
    <category type="Disposal">Washing Machines</category>
</categories>

我究竟做错了什么 ?

编辑:

它似乎是根据 only 的第一个<text><entrydata>而不是所有<text>值进行排序的。

但是这个样式表工作正常:

<?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:key name="k1" match="entrydata[@name = 'Waste' or @name = 'Disposal']//text" use="concat(ancestor::entrydata/@name, '|', .)"/>

    <xsl:template match="viewentries">
        <categories>
            <xsl:apply-templates select="viewentry/entrydata[@name =  'Waste' or @name = 'Disposal']//text
            [generate-id() = generate-id(key('k1', concat(ancestor::entrydata/@name, '|', .))[1])]">
                <xsl:sort select="."/>          
            </xsl:apply-templates>
        </categories>
    </xsl:template>

    <xsl:template match="text[normalize-space() != '']">
        <category type="{ancestor::entrydata/@name}">
            <xsl:value-of select="."/>
        </category>
    </xsl:template>

</xsl:stylesheet>

有人可以解释为什么第一个示例不起作用但第二个示例起作用。

4

1 回答 1

2

谁能解释为什么将排序应用于第一个模板有效,但是当将其应用于第二个模板时,就像我原来的问题一样,它没有????

这是您的“第二个模板”:

<xsl:template match="text[normalize-space() != '']">
    <category type="{ancestor::entrydata/@name}">
        <xsl:apply-templates>
                <xsl:sort select="."/>            
        </xsl:apply-templates>
    </category>
</xsl:template>

在这里,您要按字符串值对当前节点的子节点进行排序。

但是,在提供的 XML 文档中,任何text元素都有一个文本节点子节点——因此没有任何东西可以排序!

在这个问题和上一个问题中,你犯了同样的错误——试图对必须排序的元素的子元素进行排序——你排序太晚了。

记住

   <xsl:apply-templates/>

是 的缩写

   <xsl:apply-templates select="child::node()"/>

所以,这意味着:将模板应用到我的孩子”——而不是“将模板应用到我”。

更新:这是问题的正确解决方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kCatVal" match="text[text()]" use="concat(../@name, '+', .)"/>

 <xsl:template match="/">
  <categories>
   <xsl:apply-templates select=
    "//text[generate-id()
               =
                generate-id(key('kCatVal',
                                 concat(../@name, '+', .)
                                 )[1]
                            )
                ]">
          <xsl:sort/>
    </xsl:apply-templates>
  </categories>
 </xsl:template>

 <xsl:template match="text">
        <category type="{../@name}"><xsl:value-of select="."/></category>
  </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<viewentries>
    <viewentry>
        <entrydata name="Waste">
            <text>Bric-a-Brac</text>
        </entrydata>
        <entrydata name="Disposal">
            <text/>
        </entrydata>
    </viewentry>
    <viewentry>
        <entrydata name="Waste">
            <textlist>
                <text>Paper</text>
                <text>Glass</text>
            </textlist>
        </entrydata>
        <entrydata name="Disposal">
            <text/>
        </entrydata>
    </viewentry>
    <viewentry>
        <entrydata name="Waste">
            <textlist>
                <text>Paper</text>
                <text>Cans</text>
            </textlist>
        </entrydata>
        <entrydata name="Disposal">
            <text>Washing Machines</text>
            <text>Cars</text>
        </entrydata>
    </viewentry>
</viewentries>

产生了想要的正确结果

<categories>
   <category type="Waste">Bric-a-Brac</category>
   <category type="">Cans</category>
   <category type="Disposal">Cars</category>
   <category type="">Glass</category>
   <category type="">Paper</category>
   <category type="Disposal">Washing Machines</category>
</categories>

说明

这种分组需要基于具有两部分的复合键进行索引。因此,use属性 ofxsl:key被指定为这两个部分的连接,由一个我们知道不能出现在它们的任何值中的字符连接在一起(当第一个关键组件的值是值的前缀时避免误报第二个关键组成部分)。

于 2012-07-18T01:22:19.323 回答