Xquery для извлечения текста в HTML - PullRequest
3 голосов
/ 23 июня 2010

Я работаю над извлечением текста из HTML-документов и хранением в базе данных.Я использую инструмент webharvest для извлечения контента.Однако я застрял на месте.Внутри webharvest я использую XQuery-выражение для извлечения данных.HTML-документ, который я анализирую, выглядит следующим образом:

              <td><a name="hw">HELLOWORLD</a>Hello world</td>

Мне нужно извлечь текст «Hello world» из приведенного выше HTML-скрипта.

Я попытался извлечь текст таким способом:

     $hw :=data($item//a[@name='hw']/text())

Однако я всегда получаю «HELLOWORLD» вместо «Hello world».

Есть ли способ извлечь «Hello World».Пожалуйста, помогите.

Что если я хочу сделать это следующим образом:

<td>
 <a name="hw1">HELLOWORLD1</a>Hello world1
 <a name="hw2">HELLOWORLD2</a>Hello world2
 <a name="hw3">HELLOWORLD3</a>Hello world3
</td>

Я хотел бы извлечь текст Hello world 2, который находится в betweeb hw2 и hw3.Я бы не хотел использовать text () [3], но есть ли какой-нибудь способ, которым я мог бы извлечь текст между / a [@ name = 'hw2'] и /a[@name='hw3'].

Ответы [ 3 ]

6 голосов
/ 23 июня 2010

Ваш xpath выбирает текст узлов a, а не текст узлов td:

$item//a[@name='hw']/text()

Измените его на:

$item[a/@name='hw']/text()

Обновление (следующие комментарии и обновление к вопросу):

Этот xpath выбирает второй текстовый узел из $item, у которого есть тег a, содержащий атрибут name, установленный в hw:

$item[a/@name='hw']//text()[2]
3 голосов
/ 23 июня 2010

Я бы не хотел использовать text () [3], но есть ли какой-нибудь способ, которым я мог бы извлечь текст между /a[@name='hw2'] and /a[@name='hw3'].

Если есть только один текстовый узелмежду двумя <a> элементами, следующее будет довольно просто:

/a[@name='hw3']/preceding::text()[1]

Если между двумя элементами имеется более одного текстового узла, то вам нужно выразитьпересечение всех текстовых узлов, следующих за первым элементом, со всеми текстовыми узлами, предшествующими второму элементу.Формула пересечения двух наборов узлов (известный как метод пересечения Кайса):

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

Итак, просто замените в приведенном выше выражении $ns1 на:

/a[@name='hw2']/following-sibling::text()

и $ns2 с:

/a[@name='hw3']/preceding-sibling::text()

Наконец, если у вас действительно есть XQuery (или XPath 2), то это просто:

   /a[@name='hw2']/following-sibling::text() 

intersect

   /a[@name='hw3']/preceding-sibling::text()
0 голосов
/ 23 июня 2010

Это обрабатывает ваш расширенный регистр, позволяя вам выбирать по значению атрибута, а не по позиции:

let $item := 
  <td>
    <a name="hw1">HELLOWORLD1</a>Hello world1
    <a name="hw2">HELLOWORLD2</a>Hello world2
    <a name="hw3">HELLOWORLD3</a>Hello world3
  </td>

return $item//node()[./preceding-sibling::a/@name = "hw2"][1]

Получает первый узел, у которого есть предшествующий элемент «a» с атрибутом имени «»HW2" .

...