前同级和 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 之间的冲突的主要内容,如果未能解决你的问题,请参考以下文章

软考知识点梳理--项目冲突管理

Spyder 和 wxPython 之间的冲突?

SimpleModal 和 Bootstrap 模态之间的冲突

jquery和bootstrap之间的冲突

jQuery版本之间冲突如何解决?

表中的 id 之间的 SQL 时间和超时冲突