XSLT 1.0对过滤的XML数据进行排序 [英] XSLT 1.0 sort on filtered XML data

查看:107
本文介绍了XSLT 1.0对过滤的XML数据进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于这个问题好吧 XSLT 1.0排序元素我不知道为什么以下内容不起作用:

Ok so based on this question XSLT 1.0 sort elements I cannot figure out why the following is not working:

我有以下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>

我在做什么错了?

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

It seems to be sorting based on the first <text> value of <entrydata> only instead of all <text> values.

但是此样式表可以正常工作:

However this stylesheet works fine:

<?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>

有人可以解释为什么第一个示例不起作用,而第二个示例可以起作用.

Can someone explain why the first example doesn't work but the second example does.

推荐答案

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

Can anyone explain why applying the sort to the first template works, but when applying it to the second template like in my original question it doesn't ????

这是您的第二个模板":

Here is your "second template":

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

您要在此处按其字符串值对当前节点的子级进行排序.

Here you want to sort the children of the current node by their string value.

但是,在提供的XML文档中,任何text元素都具有单个text-node子元素-因此,没有任何要排序的东西!

However, in the provided XML document any text element has a single text-node child -- therefore there isn't anything to sort!

在此问题和上一个问题中,您都会提交相同的错误-尝试对必须排序的元素的子元素进行排序-您的排序时间太晚了.

In this and in the previous question you commit the same error -- trying to sort the children of the elements that must be sorted -- you are sorting too-late.

记住:

   <xsl:apply-templates/>

的缩写:

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

因此,这意味着:将模板应用于我的孩子"而不是将模板应用于我".

So, this means: apply templates to my children" -- not "apply templates to me".

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

Update: Here is a correct solution to the problem:

<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>

说明:

这种分组需要基于包含两个部分的组合键进行索引.因此,将xsl:keyuse属性指定为这两个部分的串联,并通过我们知道它们的任何值均不能存在的字符将它们连接在一起(以避免在第一个键组件的值出现时出现假正数)是第二个键组件的值的前缀.)

This kind of grouping requires indexing based on a composite key that has two parts. Therefore the use attribute of xsl:key is specified as the concatenation of these two parts, joined together by a character that we know cannot be present in any of their values (to avoid false-positives when a value of the first key component is a prefix of a value of the second key component).

这篇关于XSLT 1.0对过滤的XML数据进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆