前同级和 xsl:sort 之间的冲突
Posted
技术标签:
【中文标题】前同级和 xsl:sort 之间的冲突【英文标题】:Conflict between preceding-sibling and xsl:sort 【发布时间】:2014-02-15 00:31:35 【问题描述】:我有这样的东西:
<Root>
<res>
<Title> XXXXXXX </Title>
<A xlink:href='#a1111'/>
<A xlink:href='#a5000'/>
<A xlink:href='#a3333'/>
<A xlink:href='#a1000'/>
</res>
<res>
<Title> YYYYYYY </Title>
<A xlink:href='#a8888'/>
<A xlink:href='#a1000'/>
</res>
<def-list>
<Criteria xml:id="a1111">
<code> CodeX </code>
Content A
</Criteria>
<Treatment xml:id="a5000">
<code> CodeT </code>
Content B
</Treatment>
<Population xml:id="a3333">
<code> CodeY </code>
Content C
</Population>
<Criteria xml:id="a1000">
<code> CodeZ </code>
Content D
</Criteria>
<Population xml:id="a8888">
<code> CodeE </code>
Content F
</Population>
</def-list>
</Root>
注意,def-list 下的每个元素都可以被多个 res 使用,例如“a1000”,这两个 res 都使用过
在我的 xslt 中,我有:
<xsl:key name='defination' match='/Root/def-list/*' use='concat("#", @xml:id)'/>
<xsl:template match="/" >
<xsl:apply-templates select='/Root/res' />
</xsl:template>
<xsl:template match="res" >
<xsl:apply-templates select='A'>
<xsl:sort select="local-name(key('mykeys', @xlink:href))" order="ascending" />
<xsl:sort select='key("mykeys", @xlink:href)/code'/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="A">
<xsl:variable name='ref' select ='@xlink:href' />
<xsl:variable name='sibling' select='./preceding-sibling::*[1][self::A]' />
<xsl:variable name='hasprecedingsibling'>
<xsl:choose>
<xsl:when test='name(key("'mykeys'", $ref)) = name(key("'mykeys'", $sibling/@xlink:href))'>
<xsl:value-of select="'true'" />
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name='title'>
<xsl:choose>
<xsl:when test='$hasprecedingsibling != ""'>
<xsl:value-of select="'AND '"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='concat(local-name(), " :")' />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:apply-templates mode="exclude-code"/>
</xsl:template>
<xsl:template match="code" mode="exclude-code" >
</xsl:template>
</xsl:stylesheet>
(XML 和 XSLT 都已简化)
输出应该是:
Criteria:
Content A
And
Content D
Population:
Content C
Treatment:
Content B
注意格式、顺序和标题应如上。
我必须使用 XSLT 1.0,而且我还使用 .NET 处理器 (XslCompiledTransform)
问题是在我使用排序更改顺序时,前同级可以使用原始顺序。
我需要两个排序元素,但我不知道如何将前同级应用于新订单而不是原始订单。有什么想法吗?
【问题讨论】:
显然,您需要使用其他方法来实现您的目标。但是,目前尚不清楚该目标是什么。为什么不提供原始未排序输入的示例,解释如何对其进行排序以及在结果中查找什么(以及为什么)。 -- 可能的提示:如果您知道如何元素被排序,那么您也知道在排序树中哪个在另一个之前。 你可以使用 XSLT 2.0 吗?或者,如果您卡在 1.0 上,您使用的是什么处理器? @IanRoberts,我必须使用 XSLT 1.0,而且我也在使用 .NET 处理器 (XslCompiledTransform) 【参考方案1】:我有这样的东西:
不,你不能有“类似这样的东西”,因为“这个”使用未定义的命名空间前缀。您的第二类也没有任何意义,因为键的另一侧没有“代码”元素。并且您的第一个排序需要升序,而不是降序,才能得到您指示的结果。
无论如何,这可以(恕我直言)被视为一个分组问题。因此,如果我们将您的输入剥离为以下内容:
<Root>
<res>
<A href='#a1111' Code='CodeX' />
<A href='#a5000' Code='CodeT' />
<A href='#a3333' Code='CodeY' />
<A href='#a1000' Code='CodeZ' />
</res>
<def-list>
<Criteria id="a1111">
Content A
</Criteria>
<Treatment id="a5000">
Content B
</Treatment>
<Population id="a3333">
Content C
</Population>
<Criteria id="a1000">
Content D
</Criteria>
</def-list>
</Root>
并应用以下样式表:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text" encoding="utf-8"/>
<xsl:key name="defById" match="def-list/*" use="concat('#', @id)" />
<xsl:key name="defByName" match="def-list/*" use="local-name()" />
<xsl:template match="/">
<xsl:for-each select="Root/res/A">
<xsl:sort select="local-name(key('defById', @href))" order="ascending"/>
<xsl:sort select="Code"/>
<xsl:variable name="name" select="local-name(key('defById', @href))" />
<xsl:choose>
<xsl:when test="@href = concat('#', key('defByName', $name)[1]/@id) ">
<xsl:value-of select="$name" />
</xsl:when>
<xsl:otherwise>
<xsl:text >AND</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text >:</xsl:text>
<xsl:value-of select="key('defById', @href)" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我们会得到这个输出:
Criteria:
Content A
AND:
Content D
Population:
Content C
Treatment:
Content B
应用 normalize-space() 并添加更多文本元素以按照您想要的方式进行格式化。
【讨论】:
对不起,这不是我想要的以上是关于前同级和 xsl:sort 之间的冲突的主要内容,如果未能解决你的问题,请参考以下文章