【问题标题】:XPath: Find Next Occurrence of an Element in an AncestorXPath:查找祖先元素中的下一次出现
【发布时间】:2019-05-31 14:31:56
【问题描述】:

我正在尝试在 sec-type='reading' 的部分中查找下一个实例。

XML 示例:

<?xml version="1.0" encoding="US-ASCII"?>
<book>
    <sec sec-type="reading">
        <title>Section 1</title>
        <p>Sample <bold>Bold</bold>Text <fn><label>1</label></fn> Some more text</p>
        <!-- more variations of stuff at various levels -->
        <sec>
            <title>Section 1.1</title>
            <p>Another paragraph with a footnote <fn><label>2</label></fn></p>
        </sec>
        <sec>
            <title>Section 1.2</title>
            <p>Another paragraph with a footnote <fn><label>3</label></fn></p>
        </sec>
    </sec>

    <sec sec-type="reading">
        <title>Section 2</title>
        <p>Sample <bold>Bold</bold>Text <fn><label>6</label></fn> Some more text</p>
        <!-- more variations of stuff at various levels -->
        <sec>
            <title>Section 2.1</title>
            <p>Another paragraph with a footnote <fn><label>8</label></fn></p>
        </sec>
        <sec>
            <title>Section 2.2</title>
            <p>Another paragraph with a footnote <fn><label>9</label></fn></p>
        </sec>
    </sec>
</book>

目的是查看 FN 标签是否在一个部分内按顺序排列。我用 6-9 对第二部分进行了编号,以便更容易查看它是否有效。

这就是我想要的:

Footnote 1 [Next: 2]
Footnote 2 [Next: 3]
Footnote 3 [Next: ]
Footnote 6 [Next: 8]
Footnote 8 [Next: 9]
Footnote 9 [Next: ]

最终目标是为Footnote 6 [Next: 8]返回警告

这是我目前得到的schematron。这给了我:

Footnote 1 [Next: 2]
Footnote 2 [Next: 3]
**Footnote 3 [Next: 6]**
Footnote 6 [Next: 8]
Footnote 8 [Next: 9]
Footnote 9 [Next: ]

它找到脚注的下一个实例。但是,我不希望它跨越这些部分 - 所以 Footnote 3 [Next: 6] 是错误的。

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    queryBinding="xslt2"  >

  <!--check if footnotes are sequential within a reading -->
  <pattern id="footnote-sequential"> 
    <rule context="fn"> 
        <let name="next" value="following::fn[1]/label/text()"/>

        <assert test="number(label/text()) > 40">
        Footnote <value-of select='label'/> 
          [Next: <value-of select="$next"/>]
      </assert>
    </rule> 
  </pattern>
</schema>

注意:断言中的number(label/text()) &gt; 40 可以捕捉此刻的一切。最终会变成number(current)+1 != number(next)

我得到的最接近的是ancestor::sec[@sec-type='reading']//following::fn[1]/label/text() - 但这会丢失“下一个”并给我这样奇怪的结果:

    Footnote 1 [Next: 1236]
    Footnote 2 [Next: 1236]
    Footnote 3 [Next: 1236]
    Footnote 6 [Next: 689]
    Footnote 8 [Next: 689]
    Footnote 9 [Next: 689]

【问题讨论】:

    标签: xpath schematron


    【解决方案1】:

    你需要intersect

    [编辑]

    $next 设置为fn 元素而不是标签文本:

    <let name="next" value="following::fn[1]"/>
    

    [/EDIT]

    转到您当前的部分并记下该部分的所有脚注:

    <let name="sect-fns" value="ancestor::sec[@sec-type='reading']//fn" />
    

    $next$sect-fns 上相交:

    <let name="next" value="$next intersect $sect-fns" />
    

    检查$next是否为空或其标签是否为number(./label) + 1

    <assert test="not($next) or number(./label) + 1 = number($next/label)">
    

    【讨论】:

    • 你的答案有效,但它有一个错字,我被网站上的霸主禁止修复。将我的 ($next) 的变量名更改为 $next_fn 并将您的变量名设为 $next_fn_inSec。所以你的答案看起来像:在 $next_fn 和 $sect-fns 上相交:&lt;let name="next_fn" value="following::fn[1]"/&gt; &lt;let name="next_fn_inSec" value="$next_fn intersect $sect-fns" /&gt; 检查 $next_fn_inSec 是否为空或其标签是否为数字(./label)+1:&lt;assert test="not($next_fn_inSec) or number(./label)+1 = number($next_fn_inSec/label)"&gt;
    • 这不是错字,我只是错误地假设$nextfn 元素,而不是标签文本。我在回答中解决了这个问题。
    • 你是绝对正确的。不知何故,我说服自己不能在 xslt/schematron 中重新定义变量。当我第一次尝试您的答案时,我一定是输入了错误的内容并错误地认为这是问题所在。再次感谢您的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多