2013-11-22 5 views
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 должны не потому, что там не являются альфа-символами между t он полужирный альфа символы
p39 должны терпят неудачу, потому что нет альфа-символы между жирным текстом и «Foo» или «бар»

Моя попытка сделать это с помощью 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".

ответ

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(), '') 
Смежные вопросы