1

有一个这样的 XML:

<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:xlink="http://www.w3.org/1999/xlink"  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"  xmlns:skos="http://www.w3.org/2004/02/skos/core#"  version="2.8.1"  vocab-version="2013-02-28" >
  <section1>
    <a xml:id="a100">
      <ref xlink:href="#aXXX"/>
      <ref xlink:href="#aYYY"/>
    </a>
  </section1>
  <section2>
    <b xml:id="aXXX">
      DataB
    </b>
    <c xml:id="aYYY">
      DataC
    </c>
    </section2>
</root>

我想应用以下 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <xsl:output method="text"  indent="yes"/>
    <xsl:strip-space elements="*" />
    <xsl:preserve-space elements="db:para db:literallayout" />
    <xsl:param name="code" />
    <xsl:key name='mykeys' match='/root/section2/*' use='concat("#", @xml:id)'/>

    <xsl:template match="/" >
        <xsl:apply-templates select='/root/section1/a/ref'>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="ref">
        <xsl:apply-templates select='key("mykeys", @xlink:href)' >
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match='b | c' >
        <xsl:value-of select="."  />
    </xsl:template>

</xsl:stylesheet>

我想要这样的输出:

DataC
DataB

注意 c 的文本应该在 b 的文本之前

我认为需要将 xsl:sort 添加到 apply-templates ,如下所示:

<xsl:sort select='/root/section2/*[concat("#", @xml:id)=current()/@xlink:href][local-name()]' order="descending" />

IE:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:db="http://docbook.org/ns/docbook"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <xsl:output method="text"  indent="yes"/>
    <xsl:strip-space elements="*" />
    <xsl:preserve-space elements="db:para db:literallayout" />
    <xsl:param name="code" />
    <xsl:key name='mykeys' match='/root/section2/*' use='concat("#", @xml:id)'/>

    <xsl:template match="/" >
        <xsl:apply-templates select='/root/section1/a/ref'>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="ref">
        <xsl:apply-templates select='key("mykeys", @xlink:href)'  >
            <xsl:sort select='/root/section2/*[concat("#", @xml:id)=current()/@xlink:href][local-name()]'  order="descending" />
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match='b | c' >
        <xsl:value-of select="."  />
    </xsl:template>

</xsl:stylesheet>

但它不起作用。</p>

请注意,排序不能基于 xml:id,因为它可以是任何东西,也不能基于文本(即 datac , datab ,...),因为它们可以是任何东西,因此排序应该基于元素名称(即,) 仅。

我试图了解 select='/root/section2/*[concat("#", @xml:id)=current()/@xlink:href][local-name()]' 的实际值是什么?所以我将它作为参数发送到模板:

 <xsl:template match="a">
   <xsl:apply-templates select='key("mykeys", @xlink:href)'  >
    <xsl:with-param name='testparameter' select='/root/section2/*[concat("#", @xml:id)=current()/@xlink:href][local-name()]'  />
   </xsl:apply-templates>
 </xsl:template>

<xsl:template match='b | c' >
    <xsl:param name='testparameter' />
    <xsl:value-of select='$testparameter' />
</xsl:template>

令人惊讶的是,它不是元素的名称,而是每个元素的文本(即 DataB 和 DataC 而不是 b 和 c ),甚至 order-type(descending) 也没有被应用。

你能帮我吗,让我知道如何获得这样的输出:

DataC
DataB

请注意 datac 和 datab 应该只能通过元素访问,这意味着我不能使用

apply-templates select='/root/section2/b' or apply-templates select='/root/section2/c'

谢谢,

4

1 回答 1

0

我认为您需要将其放入xsl:sort应用模板中ref

这似乎工作......

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <xsl:output method="text"  indent="yes"/>
    <xsl:strip-space elements="*" />
    <xsl:param name="code" />
    <xsl:key name='mykeys' match='/root/section2/*' use='concat("#", @xml:id)'/>

    <xsl:template match="/" >
        <xsl:apply-templates select='/root/section1/a/ref'>
            <xsl:sort select="local-name(key('mykeys', @xlink:href))" order="descending"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="ref">
        <xsl:apply-templates select='key("mykeys", @xlink:href)' />     
    </xsl:template>

    <xsl:template match='b | c' >
        <xsl:value-of select="."  />
    </xsl:template>

</xsl:stylesheet>

此外,[local-name()]在这种情况下使用只是检查元素是否具有本地名称。我不认为这是你想要的。

如果你想使用local-name()把你的 XPath 作为参数来local-name()like: local-name(/some/xpath/*)。(在 XPath 2.0/XSLT 2.0 中,您也可以将其放在local-name()路径的末尾,例如:/some/xpath/*/local-name()

于 2013-08-29T06:07:53.783 回答