2010-06-23 2 views
3

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

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

Мне нужно извлечь «Hello World» текст из приведенных выше HTML сценария.

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

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

Однако то, что я всегда получаю «HelloWorld» вместо «Привет мир».

Есть ли способ извлечь «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> 

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

+0

Хороший вопрос (+1). См. Мой ответ для решения, которое вам, скорее всего, понадобится. –

ответ

6

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

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

изменить его к этому:

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

Update (после комментариев и обновления на вопрос):

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

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

Это не работает для меня. FYI $ пункт содержит весь HTML страницу как XML – Technocrat

+0

Что делать, если HTML содержит: HELLOWORLD1 Здравствуйте мира1 HELLOWORLD2 Здравствуйте world2 HELLOWORLD3 Здравствуйте world3 я хочу, чтобы извлечь только Hello world2 без использования текста (2) [ 2]. Есть ли способ указать «извлечь текст после/a [@ name =« hw1 »и до/a [@ name =« hw2 » – Technocrat

+0

@Technocrat - ответьте обновленно, следуя расширенному объяснению. – Oded

0

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

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» предыдущего родителя с атрибутом name «hw2».

2

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

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

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

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

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