Как? xmlstarlet для извлечения данных HTML по идентификатору
У меня есть простая задача, которая заставила меня вытащить мои волосы, я уверен, что я очень близко.
вот мой файл 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, мне нужны данные.
заблаговременно.
Ответы
Ответ 1
Данные 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
UPDATE: я не знал об этом, но, как говорится в сообщении об ошибке, нет необходимости объявлять пространство имен, когда оно по умолчанию, так что это работает:
xmlstarlet sel \
-t \
-c "/_:html/_:body/_:table[@id='test_table']/descendant::*/text()" \
htmlfile 2>/dev/null
Ответ 2
Как упоминается в
http://xmlstar.sourceforge.net/doc/UG/ch05.html
общие проблемы при использовании
-N x="http://www.w3.org/1999/xhtml" \
вы также должны префикс выбора node с помощью
x:
например.
xmlstarlet sel \
-N x="http://www.w3.org/1999/xhtml" \
-t \
-m "//x:pre" \
-v . somehtml.html
выберет все предварительные узлы
Ответ 3
Вы можете попробовать
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