2010-02-17 3 views
3

Я пытаюсь выбрать элементы (a) с XPath 1.0 (или, возможно, с Regex), которые следуют за братьями и сестрами определенного элемента (b), но только предшествуют другому элементу b.XPath "следующие братья и сестры до"

<img><b>First</b><br>&nbsp;&nbsp; 
<img>&nbsp;&nbsp;<a href="/first-href">First Href</a> - 19:30<br> 
<img><b>Second</b><br>&nbsp;&nbsp; 
<img>&nbsp;&nbsp;<a href="/second-href">Second Href</a> - 19:30<br> 
<img>&nbsp;&nbsp;<a href="/third-href">Third Href</a> - 19:30<br> 

Я попытался сделать образец как можно ближе к реальному миру. Таким образом, в этом случае, когда я в элементе

<b>First</b> 

нужно выбрать

<a href="/first-href">First Href</a> 

и когда я на

<b>Second</b> 

нужно выбрать

<a href="/second-href">Second Href</a> 
<a href="/third-href">Third Href</a> 

Любая идея, как достичь этого? Спасибо!

+0

Можно ли считать, что xml хорошо сформирован, то есть элементы 'br' на самом деле'
'?Кроме того, элементы 'img' имеют контент и заканчиваются символом' /> '? Это действительно помогло бы, если бы «реальный мир» включал хорошо сформированный XML, если не XPath не является вариантом. – AnthonyWJones

+0

Будучи примером реального мира, конечно, он не очень хорошо сформирован. Я бы хотел, чтобы это было :(Однако я использую Html Agility Pack (.NET) для обработки разметки и переносит плохо сформированные документы, если это какая-то помощь. –

+0

Нет причин предполагать, что «реальный мир» подразумевает -форматный xml. Есть много примеров html, поставляемых как хорошо сформированный xml. Конечно, вы упомянули о маневренности в вопросе, который он бы сделал сценарием более ясным. Добавлен соответствующий тег. – AnthonyWJones

ответ

5

Динамически создать этот XPath:

following-sibling::a[preceding-sibling::b[1][.='xxxx']] 

где 'хххх' является заменяется текстом текущего <b>.

Предполагается, что все элементы на самом деле являются братьями и сестрами. Если это не так, вы можете попытаться работать с осями preceding и following или написать более конкретный XPath, который лучше напоминает структуру документа.

В XSLT можно также использовать:

following-sibling::a[ 
    generate-id(preceding-sibling::b[1]) = generate-id(current()) 
] 
1

Вот решение, которое только одно выражение XPath.

Используя формулу Kaysian для пересечения два nodesets $ns1 и $ns2:

$ns1[count(. | $ns2) = count($ns2)] 

Мы просто заменить $ns1 с набором узлами из <a> братий, которые следуют за текущий <b> узлом, и подставят $ns2 с набором узлов от <a> братьев и сестер, предшествующих следующему <b> узла.

Вот полное преобразование, которое использует этот:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="*/b"/> 
    </xsl:template> 

    <xsl:template match="b"> 
    At: <xsl:value-of select="."/> 

    <xsl:variable name="vNextB" select="following-sibling::b[1]"/> 

    <xsl:variable name="vA-sAfterCurrentB" select="following-sibling::a"/> 

    <xsl:variable name="vA-sBeforeNextB" select= 
    "$vNextB/preceding-sibling::a 
    | 
    $vA-sAfterCurrentB[not($vNextB)] 
    "/> 

    <xsl:copy-of select= 
    "$vA-sAfterCurrentB 
       [count(.| $vA-sBeforeNextB) 
       = 
       count($vA-sBeforeNextB) 
       ] 
    "/> 
    </xsl:template> 
</xsl:stylesheet> 

Когда это преобразование применяется на следующий документ XML:

<t> 
    <img/> 
    <b>First</b> 
    <br />&#xA0;&#xA0; 
    <img/>&#xA0;&#xA0; 
    <a href="/first-href">First Href</a> - 19:30 
    <br /> 
    <img/> 
    <b>Second</b> 
    <br /> 
    <img/>&#xA0;&#xA0; 
    <a href="/second-href">Second Href</a> - 19:30 
    <br /> 
    <img/>&#xA0; 
    <a href="/third-href">Third Href</a> - 19:30 
    <br /> 
</t> 

правильный результат производится:

At: First <a href="/first-href">First Href</a> 
    At: Second <a href="/second-href">Second Href</a> 
<a href="/third-href">Third Href</a> 
Смежные вопросы