XSLT中的Gobal计数器还是替代解决方案?

XSLT中的Gobal计数器还是替代解决方案?,xslt,xslt-2.0,Xslt,Xslt 2.0,这是我的源XML。它最初是一个单词ML,已经简化为自己的结构。名为“aaa”的元素可以有任何类型的名称。问题在于脚注的处理: <root> <doc> <comment>text text text <footnote id="1" > text text text</comment> <aaa>text text text</aaa> <aaa>text text tex

这是我的源XML。它最初是一个单词ML,已经简化为自己的结构。名为“aaa”的元素可以有任何类型的名称。问题在于脚注的处理:

<root>
  <doc>
    <comment>text text text <footnote id="1" > text text text</comment>
    <aaa>text text text</aaa>
    <aaa>text text text<footnote id="2" /> text text text </aaa>
    <aaa>text text text<aaa/> text <footnote id="3" symbol="*"/></aaa>
    <aaa>text text text text</aaa>
    <aaa>text text text text<aaa>text text text<footnote id="4"  /></aaa></aaa>
 <aaa>text text text text<aaa>text text text<footnote id="4"  /></aaa></aaa>
 <aaa>text text text text<aaa>text text text<footnote id="5"  /></aaa></aaa>
    <aaa>text text text</aaa>
  </doc>
</root>

文本文本文本文本文本文本文本
文本文本文本
文本文本文本文本文本文本文本
文本文本文本文本
文本文本文本文本
文本文本文本文本文本文本文本
文本文本文本文本文本文本文本
文本文本文本文本文本文本文本
文本文本文本
我必须将这个源XML转换成另一个XML。我要做的一件事是用相应的数字替换脚注

但不可能只使用ID属性。ID只是一个内部编号。脚注应是渐进式的,并且存在以下条件:

  • 条件1:应忽略节点“注释”的子节点“脚注”。忽略整个节点“注释”
  • 条件2:具有符号属性的“脚注”不计算在内(我必须显示符号,而不是数字)
  • 条件3:某些注释可能具有相同的id(只有很低的百分比,但有时有更多指向同一脚注的链接)
输出应该是这样的(结构不一样,现在只对脚注的处理感兴趣):


文本文本文本
文本[1]文本文本
文本[*]
文本文本文本文本
文本文本[2]
文本文本[2]
文本文本[3]
文本文本文本
我的第一个想法是有一个全局计数器变量,我根据条件递增它。但由于XSLT中的变量是不可变的,所以它实际上不是一个选项

我还试图数一数在当前脚注之前出现的先前脚注

        <xsl:template match="footnote">
         <xsl:call-template name="getFootnoteNumber">
          <xsl:with-param name="footNodeId" select="@id"/>
         </xsl:call-template>
        </xsl:template>

    <!-- simple template which only counts the footnotes
    that occur before the current footnode 
    the conditions 1, 2 and 3 are not yet included -->
        <xsl:template name="getFootnoteNumber">
           <xsl:param name="footNodeId"/>
           <xsl:value-of select="count(//footnote[position()&lt;=$footNodeId])"></xsl:value-of>     
    </xsl:template>
    <!-- i mostly get value "0", 
    or other strange numbers: for footNodeID=45 i get value 75, 
    doesn't really work-->

是否有可能开发一个全球计数器

还是我必须换一种方式数一数前面的脚注?虽然我真的不知道如何实现条件3

您好,谢谢您的回答 cpt.oneeye

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="foot" match="footnote[not(ancestor::comment)][not(@symbol)]" use="@id"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="footnote[ancestor::comment]" priority="1" />
    <xsl:template match="footnote[@symbol]">
        <xsl:value-of select="concat('[',@symbol,']')"/>
    </xsl:template>
    <xsl:template match="footnote">
        <xsl:value-of select="concat('[',count(key('foot',@id)[1]/preceding::footnote[generate-id(.)=generate-id(key('foot',@id)[1])])+1,']')"/>
    </xsl:template>
</xsl:stylesheet>

如果输入正确:

<root>
    <doc>
        <comment>text text text <footnote id="1" /> text text text</comment>
        <aaa>text text text</aaa>
        <aaa>text text text <footnote id="2" /> text text text</aaa>
        <aaa>text text text <aaa/>text <footnote id="3" symbol="*"/></aaa>
        <aaa>text text text text</aaa>
        <aaa>text text text text <aaa>text text text <footnote id="4"  /></aaa></aaa>
        <aaa>text text text text <aaa>text text text <footnote id="4"  /></aaa></aaa>
        <aaa>text text text text <aaa>text text text <footnote id="5"  /></aaa></aaa>
        <aaa>text text text</aaa>
    </doc>
</root>

文本文本文本文本文本文本文本
文本文本文本
文本文本文本文本文本文本文本
文本文本文本文本
文本文本文本文本
文本文本文本文本文本文本文本文本
文本文本文本文本文本文本文本文本
文本文本文本文本文本文本文本文本
文本文本文本
结果:

<root>
    <doc>
        <comment>text text text  text text text</comment>
        <aaa>text text text</aaa>
        <aaa>text text text [1] text text text</aaa>
        <aaa>text text text <aaa></aaa>text [*]</aaa>
        <aaa>text text text text</aaa>
        <aaa>text text text text <aaa>text text text [2]</aaa></aaa>
        <aaa>text text text text <aaa>text text text [2]</aaa></aaa>
        <aaa>text text text text <aaa>text text text [3]</aaa></aaa>
        <aaa>text text text</aaa>
    </doc>
</root>

文本文本文本文本文本文本文本
文本文本文本
文本[1]文本文本
文本[*]
文本文本文本文本
正文[2]
正文[2]
正文[3]
文本文本文本

编辑:布拉克斯小姐。接下来,我将发布一个答案,前面没有轴。

XSLT2.0解决方案:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:key name="kPosById" match="@pos" use="../@id"/>

 <xsl:variable name="vdistinctFootnotes">
  <xsl:for-each-group group-by="@id" select=
    "/*/*/*[not(self::comment)]//footnote[not(@symbol)]">

    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:attribute name="pos" select="position()"/>
    </xsl:copy>
  </xsl:for-each-group>
 </xsl:variable>

    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="footnote">
      <xsl:value-of select=
      "concat('[', key('kPosById', @id, $vdistinctFootnotes), ']')"/>
    </xsl:template>

    <xsl:template match="footnote[@symbol]">
     <xsl:value-of select="concat('[', @symbol, ']')"/>
    </xsl:template>

    <xsl:template match="footnote[ancestor::comment]"/>
</xsl:stylesheet>

当此转换应用于提供的文档时(更正为格式正确):


文本文本文本文本文本文本文本
文本文本文本
文本文本文本文本文本文本文本
文本文本文本文本
文本文本文本文本
文本文本文本文本文本文本文本
文本文本文本文本文本文本文本
文本文本文本文本文本文本文本
文本文本文本
产生所需结果

<root>
  <doc>
    <comment>text text text  text text text</comment>
    <aaa>text text text</aaa>
    <aaa>text text text[1] text text text </aaa>
    <aaa>text text text<aaa/> text [*]</aaa>
    <aaa>text text text text</aaa>
    <aaa>text text text text<aaa>text text text[2]</aaa></aaa>
 <aaa>text text text text<aaa>text text text[2]</aaa></aaa>
 <aaa>text text text text<aaa>text text text[3]</aaa></aaa>
    <aaa>text text text</aaa>
  </doc>
</root>

文本文本文本文本文本文本文本
文本文本文本
文本[1]文本文本
文本[*]
文本文本文本文本
文本文本[2]
文本文本[2]
文本文本[3]
文本文本文本

很好的解决方案,但是依靠前面的:轴可能会有点低效(O(N^2)):@Dimitre:是的!XSLT1.0没有p/3
函数。但是,如何计算O(N^2)复杂度呢?这是对O(N/2*N+1)的一般解释(假设“查找前置项”作为算法复杂性单元?@Alejandro:在XSLT1.0中,可以使用
键()
在多个文档上运行函数。有一个技巧可以做到这一点。@Alejandro:非常感谢您提供的解决方案。当我在原始xmlsource上使用xsl时,效果非常好。但是当我将代码添加到现有xsl中时,它只对一些FootNode有效。大多数情况下,我得到的是“1”作为输出。必须与xsl的另一部分发生冲突,我还没有弄清楚。@Dimitre:是的。可以对上下文中的任何文档使用
(例如,为每个,使用
更改上下文),但对于构建“同类第一”
脚注
的文档,我必须使用
节点集()
XSLT1.0中的扩展,我是一个顽固的标准XSLT1.0人。
<root>
  <doc>
    <comment>text text text <footnote id="1" /> text text text</comment>
    <aaa>text text text</aaa>
    <aaa>text text text<footnote id="2" /> text text text </aaa>
    <aaa>text text text<aaa/> text <footnote id="3" symbol="*"/></aaa>
    <aaa>text text text text</aaa>
    <aaa>text text text text<aaa>text text text<footnote id="4"  /></aaa></aaa>
 <aaa>text text text text<aaa>text text text<footnote id="4"  /></aaa></aaa>
 <aaa>text text text text<aaa>text text text<footnote id="5"  /></aaa></aaa>
    <aaa>text text text</aaa>
  </doc>
</root>
<root>
  <doc>
    <comment>text text text  text text text</comment>
    <aaa>text text text</aaa>
    <aaa>text text text[1] text text text </aaa>
    <aaa>text text text<aaa/> text [*]</aaa>
    <aaa>text text text text</aaa>
    <aaa>text text text text<aaa>text text text[2]</aaa></aaa>
 <aaa>text text text text<aaa>text text text[2]</aaa></aaa>
 <aaa>text text text text<aaa>text text text[3]</aaa></aaa>
    <aaa>text text text</aaa>
  </doc>
</root>