如何? xmlstarlet 通过 id 提取 HTML 数据

问题描述 投票:0回答:3

我有一个简单的任务,需要我把头发拔出来,我确信我已经非常接近了。

这是我的 xhtml 文件:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title>Test Page</title>
</head>

<body>

<p>
test
</p>

<table id="test_table">
<tr><td>test</td><td>test</td></tr>
<tr><th>mo test</th></tr>
</table>

</body>

</html>

...并且 xmlstarlet 喜欢它:

$ xmlstarlet.exe el -v test.xhtml
html[@xmlns='http://www.w3.org/1999/xhtml']
html/head
html/head/title
html/body
html/body/p
html/body/table[@id='test_table']
html/body/table/tr
html/body/table/tr/td
html/body/table/tr/td
html/body/table/tr
html/body/table/tr/th

我需要做的是提取表格标签中的数据,最好没有 HTML。 其背景是我正在编写一个测试集,其中调用网页然后写入文件。 该测试要求我验证表数据,但如果页面上的其他内容发生变化,则允许测试成功。 另外,我不会提前知道表格将有多少列或行,它可能会根据数据而变化。

但是当我尝试时:

$ xmlstarlet.exe sel -t -c "/html/body/table[@id='test_table']" test.xhtml
Attempt to load network entity http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
None of the XPaths matched; to match a node in the default namespace
use '_' as the prefix (see section 5.1 in the manual).
For instance, use /_:node instead of /node

不同的测试需要不同的 id,但它们都有唯一的 id 值。 所以,给定 xhthml 中的任何“id”,我需要它的数据。

提前致谢。

xml xhtml xmlstarlet
3个回答
13
投票

html
数据有一个默认命名空间,您必须在
xmlstarlet
命令中声明:

xmlstarlet sel \
    -N n="http://www.w3.org/1999/xhtml" \
    -t \
    -c "/n:html/n:body/n:table[@id='test_table']/descendant::*/text()" \
htmlfile 2>/dev/null

找到

<table>
元素后,我使用
descendant::*/text()
提取它的所有文本元素,并使用
2>/dev/null
跳过警告:

Attempt to load network entity http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd

它产生:

testtestmo test

更新:我不知道,但正如错误消息所示,当命名空间是默认命名空间时,无需声明命名空间,所以这也有效:

xmlstarlet sel \
    -t \
    -c "/_:html/_:body/_:table[@id='test_table']/descendant::*/text()" \
htmlfile 2>/dev/null

1
投票

正如

中提到的

http://xmlstar.sourceforge.net/doc/UG/ch05.html

使用时常见问题

-N x="http://www.w3.org/1999/xhtml" \

您还必须为节点选择添加前缀

x:

例如

 xmlstarlet sel \
  -N x="http://www.w3.org/1999/xhtml" \
  -t \
  -m "//x:pre" \
  -v . somehtml.html

将选择所有前置节点


-1
投票

你可以试试

xmlstarlet ed --inplace -u "html/body/table[@id='your_tabl e_id']/tr[@id='row_id']/td[@id='data_id']" -v NEW_VALUE_TO_BE_CHANGED HTMLFILE_NAME 2>/dev/null
© www.soinside.com 2019 - 2024. All rights reserved.