2014-02-25 13 views
12

Ich habe eine einfache Aufgabe, die mich zieht meine Haare aus, ich bin mir sicher, dass ich sehr nah bin.wie? xmlstarlet zum Extrahieren von HTML-Daten durch ID

hier ist meine xhtml-Datei:

<!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> 

... und xmlstarlet gefällt es:

$ 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 

, was ich die Daten in der Tabelle Tag tun müssen, ist zu extrahieren, vorzugsweise ohne HTML . Der Kontext dafür ist, dass ich einen Testsatz schreibe, in dem eine Webseite aufgerufen und dann in eine Datei geschrieben wird. Der Test erfordert, dass ich die Tabellendaten validiere, aber den Test erfolgreich ausführen lasse, wenn sich andere Dinge auf der Seite ändern. Außerdem weiß ich nicht im Voraus, wie viele Spalten oder Zeilen die Tabelle haben wird, sie kann basierend auf den Daten variieren.

aber wenn ich versuche:

$ 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 

gibt es verschiedene IDs i für verschiedene Tests benötigen, aber sie alle haben eindeutige ID-Werte. Also, wenn ich eine 'ID' in xhthml habe, brauche ich die Daten.

danke im voraus.

Antwort

7

Die html Daten hat einen Standard-Namespace, die Sie im xmlstarlet Befehl zu erklären haben:

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 

Sobald das <table> Element befindet ich descendant::*/text() verwenden, um alle Textelemente zu extrahieren, und auch 2>/dev/null verwenden, um überspringen die Warnung:

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

Es ergibt:

testtestmo test 

UPDATE: Ich wusste es nicht, aber als die Fehlermeldung sagt, gibt es keine Notwendigkeit, den Namensraum zu erklären, wenn es der Standard eine ist, so funktioniert das auch:

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

Danke danke danke !!! Jetzt verstehe ich die Fehlermeldung auch! aber ich hätte auch niemals die Nachfahrensyntax erraten. –

0

Wie wird in

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

gemeinsame Probleme erwähnt, wenn die

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

Option müssen Sie auch mit

x: 

zum Beispiel die Knotenauswahl Präfix

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

werden alle pre Knoten

-1

wählen Sie können versuchen,

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 
+0

das wird definitiv funktionieren –

Verwandte Themen