previous-sibling和xsl:sort之间的冲突

时间:2014-01-24 05:57:31

标签: xml sorting xslt

我有这样的事情:

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

问题是,在我使用sort更改订单时,previous-sibling与原始订单一起使用。

我需要两个排序元素,但我不知道如何将先前兄弟应用于新顺序而不是原始顺序。有什么想法?

1 个答案:

答案 0 :(得分:0)

  

我有这样的事情:

不,你不能拥有这样的东西&#34;因为&#34;这个&#34;使用未定义的名称空间前缀。你的第二种也没有意义,因为没有`Code&#39;钥匙另一边的元素。您的第一个排序需要升序,而不是降序以获得您指明的结果。

无论如何,这可以(和恕我直言)应该被视为一个分组问题。所以,如果我们将你的输入剥离成这样的东西:

<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()并添加更多文本元素,以便按照您希望的方式对其进行格式化。