Как выбрать все элементы между двумя узлами с XPath - PullRequest
4 голосов
/ 02 марта 2012

Как мне выбрать все (все возможные узлы) между 1-м и вторым h2? Между ними может быть n узлов, и может быть m h2 тегов.

Узлы не обязательно будут содержаться в элементе HTML, поэтому селектор может просто захватить их все.

<html>
 <h2>asdf</h2>
 <p>good stuff 1</p>
 <p>good stuff 2</p>
 <p>good <a href="#">asdf</a>stuff n...</p>
 <h2>qwer</h2>
 <p>test2</p>
 <h2>dfgh</h2>
 <p>test2</p>
</html>

Я просто мокну от XPath. Пожалуйста, помогите мой вопрос новичка:)

Большое спасибо!

Ответы [ 4 ]

4 голосов
/ 02 марта 2012

Одно выражение XPath, которое выбирает требуемые элементы: :

   /*/h2[1]
      /following-sibling::p
        [count(. | /*/h2[2]/preceding-sibling::p)
        =
         count(/*/h2[2]/preceding-sibling::p)
        ]

В общем, в таких случаях можно использовать формулу Кейсиана для пересечения множества:

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

Это выражение XPath выбирает все узлы, принадлежащие и к наборам узлов $ns1 и $ns2.

Если вы хотите получить все узлы между двумя заданными узлами $ n1 и$ n2, это пересечение двух наборов узлов: $n1/following-sibling::node() и $n2/preceding-sibling::node().

Просто подставьте эти выражения в формулу Кейсиана, и вы получите искомое выражение XPath.

Конечно, в XPath 2.0 можно использовать оператор << или >>, например:

 /*/h2[1]/following-sibling::p[. << /*/h2[1]/]
1 голос
/ 02 марта 2012

Не уверен насчет xpath, но у вас есть тег C # 4.0, поэтому следующий код выполняет свою работу:

XElement.Parse(xml)
                .Element("h2")
                .ElementsAfterSelf()
                .TakeWhile(n => n.Name != "h2")
                .ToList()
0 голосов
/ 02 марта 2012

я знаю, что это не рабочий пример, но его почти нет,

все, что вам действительно нужно сделать, это исправить синтаксические ошибки и, возможно, исправить рекурсивные элементы

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()">
    <xsl:call-template name="tmpMatchNode">
      <xsl:with-param name="indx" select="0"/>
      <xsl:with-param name="self" select="node()"/>
    </xsl:call-template>
  </xsl:template>
  <xsl:template name="tmpMatchNode" >
    <xsl:variable name="indx" />
    <xsl:variable name="self"/>

    <xsl:element name="name($self[index])">
      <xsl:value-of select="$self[$indx]"/>
    </xsl:element>
    <xsl:choose>
      <xsl:when test="$self[$indx+1]:name() != 'H2'">
        <xsl:call-template name="tmpMatchNode">
          <xsl:with-param name="indx" select="$indx +1"/>
          <xsl:with-param name="self" select="$self"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$self[$indx]:name() = 'H2'">
        <xsl:call-template name="tmpMatchNode">
          <xsl:with-param name="indx" select="$indx +1"/>
          <xsl:with-param name="self" select="$self"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:comment>DO NOTHING HERE AS WE HAVE NOTHING TO DO</xsl:comment>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
0 голосов
/ 02 марта 2012

Как-то так должно работать (хотя и не использует XPath)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...