1

考虑以下 XML:

<paratext ID="p34"><bold>pass</bold> <bold>pass</bold></paratext>
<paratext ID="p35"><bold>pass</bold></paratext>
<paratext ID="p36">foo <bold>pass</bold> bar</paratext>
<paratext ID="p37">foo<bold> pass </bold>bar</paratext>
<paratext ID="p38"><bold>fail</bold><bold>fail</bold></paratext>
<paratext ID="p39">foo<bold>fail</bold>bar</paratext>

p34 应该通过,因为粗体标签的字母之间没有字母
p35 应该通过,因为粗体标签的外部没有字母字符
p36 应该通过,因为粗体文本和其他文本之间没有字母
p37 应该通过,因为粗体文本和其他文本
之间没有字母 p38 应该失败,因为粗体 alpha 字符之间没有 alpha 字符
p39 应该失败,因为粗体文本和“foo”或“bar”之间没有 alpha 字符

我通过 schematron 尝试这样做是这样的:

<iso:rule context="//jd:csc|//jd:bold|//jd:ital|//jd:underscore">
 <iso:assert test="   
    string-length(preceding-sibling::text()) = 0
    or      
    matches(substring(preceding-sibling::text(), string-length(preceding-sibling::text())), '[^a-zA-Z]')
    or
    matches(substring(.,1,1), '[^a-zA-Z]')
    ">
    {WS1046} An .alpha character cannot both immediately preceed and follow &lt;<iso:value-of select="name()"/>&gt; tag
 </iso:assert>
 <iso:assert test="  
    string-length(following-sibling::text()) = 0
    or
    matches(substring(following-sibling::text(), 1,1), '[^a-zA-Z]')
    or
    matches(substring(., string-length(.)), '[^a-zA-Z]')
    ">
    {WS1046} An .alpha character cannot both immediately preceed and follow &lt;/<iso:value-of select="name()"/>&gt; tag
 </iso:assert>
</iso:rule>

这样做的问题是它只查看当前上下文的父级的直接子文本节点。因此,p38 不会失败,因为没有直接的子文本节点。此外,类似的东西b<foo>bar <bold>pass</bold>会失败,因为它只会看到“b”preceding-sibling::text()而不会看到"foo ".

我也尝试过::*/text()代替::text(),但后来我遇到了类似的问题,因为我只看到兄弟元素中的文本,没有得到直接的兄弟文本节点。我需要把这两个东西放在一起,有人知道怎么做吗?


例如,在这个 xml 中:

<paratext ID="p1">hello <foo>bar</foo> <bold>THIS</bold> <foo>bar</foo>goodbye</paratext>

当上下文规则命中<bold>THIS</bold>并检查前面时,我希望它看到"hello bar ",当检查以下时,我希望它看到" bargoodbye".

4

1 回答 1

3

使用 XPath 2.0(您似乎在使用时使用matches)您可以使用:

string-join(preceding-sibling::node(), '') 

得到"hello bar ",并且:

string-join(following-sibling::node(), '') 

得到" bargoodbye".

以上几行假设您只有元素和文本节点作为兄弟节点。如果可能有评论和/或处理指令,并且您想忽略这些规则的内容,您可以使用:

string-join(preceding-sibling::* | preceding-sibling::text(), '')
于 2013-11-22T17:02:57.643 回答