首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSLT1.0对过滤的XML数据的排序

XSLT1.0对过滤的XML数据的排序
EN

Stack Overflow用户
提问于 2012-07-17 13:35:38
回答 1查看 334关注 0票数 1

好的,基于这个问题,XSLT 1.0 sort elements,我不明白为什么以下内容不起作用:

我有以下XML:

代码语言:javascript
复制
<?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:

代码语言:javascript
复制
<?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>

这提供了以下输出:

代码语言:javascript
复制
<?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>

我需要按顺序排序的输出:

代码语言:javascript
复制
<?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>

我做错什么了?

编辑:

它似乎只基于<entrydata>的第一个<entrydata>值而不是所有<text>值进行排序。

然而,这个样式表工作得很好:

代码语言:javascript
复制
<?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>

有人能解释为什么第一个例子不起作用,而第二个例子却起作用。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-07-18 01:22:19

有人能解释为什么将排序应用于第一个模板是有效的,但是当应用于第二个模板时,就像我在最初的问题中那样,它不会?

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

代码语言:javascript
复制
<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元素都有一个文本--节点子--因此没有任何可以排序的东西!

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

记住

代码语言:javascript
复制
   <xsl:apply-templates/>

的缩写

代码语言:javascript
复制
   <xsl:apply-templates select="child::node()"/>

因此,这意味着:将模板应用于我的孩子“--而不是”将模板应用到我身上“。

Update:下面是一个正确的解决方案:

代码语言:javascript
复制
<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文档上应用时

代码语言:javascript
复制
<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>

想要的,正确的结果产生

代码语言:javascript
复制
<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>

Explanation

这种分组要求基于包含两个部分的复合键进行索引。因此,use属性xsl:key被指定为这两个部分的连接,由我们知道它们的值中不存在的一个字符连接在一起(以避免当第一个键组件的值是第二个键组件的值的前缀时出现假阳性)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11523678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档