考虑以下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应该通过,因为粗体标签外面没有alpha字符 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 <<iso:value-of select="name()"/>> 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 </<iso:value-of select="name()"/>> tag
</iso:assert>
</iso:rule>
这个问题是它只查看当前上下文的父项的直接子文本节点。因此,p38不会失败,因为没有直接的子文本节点。此外,b<foo>bar <bold>pass</bold>
之类的内容会失败,因为它只会在preceding-sibling::text()
中看到“b”,而不会看到"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"
。
答案 0 :(得分:2)
使用XPath 2.0(您似乎在使用matches
时使用),您可以使用:
string-join(preceding-sibling::node(), '')
获取"hello bar "
,并且:
string-join(following-sibling::node(), '')
获取" bargoodbye"
。
以上几行假设您只有元素和文本节点作为兄弟节点。如果可以提供评论和/或处理说明,并且您希望忽略这些规则的内容,则可以使用:
string-join(preceding-sibling::* | preceding-sibling::text(), '')