2010-07-13 46 views
1

这是我的Source-XML。它最初是一个Word-ML,已经被简化为一个自己的结构。名称为“aaa”的元素可以具有任何种类的名称。问题是处理脚注:XBTT或替代解决方案中的全局计数器?

<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中转换此Source-XML。我必须做的一件事是用对应号码替换脚注。

但是不可能仅使用ID属性。该ID只是一个内部号码。脚注应该是渐进式的,并且有以下情况:

  • 条件1:应该忽略作为节点“评论”的子节点的“脚注”。整个节点“评论”被忽略。
  • 条件2:具有符号属性的“脚注”不计数(我必须显示符号而不是数字)
  • 条件3:某些笔记可能具有相同的ID(只有低百分比,但有时会有更多链接指向同一个脚注)。

输出应该是这样的(结构不是脚注一样的,只是处理是利息现在):

<root> 
    <doc> 
    <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> 

我首先想到的是有一个全球性的反变量,我根据条件增加。但是由于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

问候和THX任何答案 cpt.oneeye

回答

1

XSLT 2。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> 

当这种转变是在所提供的文档施加(校正为简洁(wellformed)):

<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> 
+0

非常感谢你。那完美的工作。 – 2010-07-14 08:15:54

2

这个样式表:

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

编辑:布兰克小姐。接下来,我会发布一个没有前置轴的答案。

+0

很好的解决方案,但依赖于':: ::轴'可能会有点低效(O(N^2)):) – 2010-07-13 16:41:51

+0

@Dimitre:是的! XSLT 1.0没有p/3'key'功能。但是,您如何计算O(N^2)复杂度?这是对O(N/2 * N + 1)的一般解释(假设“查找前面的”作为算法复杂度单元? – 2010-07-13 23:15:04

+1

@Ajjandro:在XSLT 1.0中,您可以在多个文档上使用'key()'函数。 – 2010-07-14 01:05:21