2010-06-23 98 views
3

我正在从HTML文档中提取文本并存储在数据库中。我正在使用webharvest工具来提取内容。不过,我有点卡住了。 webarvest内部我使用XQuery表达式来提取数据。那我解析HTML文件如下:Xquery在HTML中提取文本

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

我需要提取从上面的HTML脚本“Hello World”文本。

我试图以这种方式提取文本:

 $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)。查看我的答案,找出您可能需要的解决方案。 – 2010-06-23 13:33:24

回答

6

你的XPath是选择a节点的文本,而不是在td节点的文本:

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

它改成这样:

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

更新(以下意见和更新以提问):

此xpath从中选择第二个文本节点具有含name属性设置为hwa标签:

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

这不是为我工作。 FYI $项目包含了整个HTML页面的XML – Technocrat 2010-06-23 11:26:54

+0

如果什么HTML包含: ​​ HELLOWORLD1你好world1 HELLOWORLD2你好world2 HELLOWORLD3你好world3 我不想使用文本只提取你好world2(2) 2]。是否有指定HW1" 和前/一[@名称=‘HW2’ – Technocrat 2010-06-23 11:34:01

+0

@Technocrat“后/ A [@名称=提取文本”的方式 - 答案更新,下面你扩大解释 – Oded 2010-06-23 12:17:08

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] 

这得到的第一个节点它具有名称属性为“hw2”的前同胞“a”元素。

2

我不想用文字()[3]但 是有一些方法,我可以提取 文本出来/a[@name='hw2'] and /a[@name='hw3']之间。

如果有两个<a>元素之间只有一个文本节点,那么下面就相当简单:

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

如果有两个元素之间不止一个文本节点,然后您需要表示第一个元素之后的所有文本节点与第二个元素之前的所有文本节点的交集。两个节点集(交点又名Kaysian方法)的交叉点计算公式为:

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

$ns2用:

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

所以,仅仅用替换在以上表达式$ns1

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

最后,如果你确实有XQuery(或XPath 2),那么这很简单:

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

intersect 

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