Grep และ Sed เทียบเท่ากับการประมวลผลบรรทัดคำสั่ง XML


147

เมื่อทำการเชลล์สคริปต์โดยทั่วไปข้อมูลจะอยู่ในไฟล์ของเร็กคอร์ดบรรทัดเดียวเช่น csv มันง่ายมากที่จะจัดการกับข้อมูลนี้กับและgrep sedแต่ฉันต้องจัดการกับ XML บ่อยครั้งดังนั้นฉันชอบวิธีเข้าถึงสคริปต์เพื่อเข้าถึงข้อมูล XML นั้นผ่านบรรทัดคำสั่ง เครื่องมือที่ดีที่สุดคืออะไร


xml_grep ใช้ได้สำหรับ grepping ตามที่ระบุไว้ในstackoverflow.com/a/2222224/871134
Deleplace

คำตอบ:


105

ฉันพบว่า xmlstarlet นั้นค่อนข้างดีสำหรับสิ่งนี้

http://xmlstar.sourceforge.net/

ควรมีอยู่ในที่เก็บ distro ส่วนใหญ่ด้วย บทแนะนำเบื้องต้นอยู่ที่นี่:

http://www.ibm.com/developerworks/library/x-starlet.html


1
คิดว่าฉันจะชี้ให้เห็นว่ามี Windows ไบนารีอยู่บนเว็บไซต์ Sourceforge
Steve Bennett

ไม่รองรับ XQuery เท่าที่ฉันสามารถบอกได้
Steve Bennett

@SteveBennett แน่นอนว่ามันไม่ได้ แต่คุณสมบัติที่เพิ่มเข้ามาบน XPath ดิบนั้นดีพอที่จะทำให้มันแข่งขันกับ "grep and sed" ถ้าคุณต้องการความแฟนซีความดีงามของ XQuery ... นั่นก็เหมือนกับ XML ที่เทียบเท่ากับ perl หรือ awk :)
ชาร์ลส์ดัฟฟี่

36

เครื่องมือที่มีแนวโน้ม:

  • nokogiri : การแยกDOM / HTML DOMs ในทับทิมโดยใช้ XPath & CSS selector

  • hpricot : เลิกใช้แล้ว

  • fxgrep : ใช้ไวยากรณ์คล้าย XPath ของตัวเองเพื่อค้นหาเอกสาร เขียนใน SML ดังนั้นการติดตั้งอาจทำได้ยาก

  • LT XML : XML เครื่องมือที่ได้มาจากเครื่องมือ SGML รวมทั้งsggrep, sgsort, xmlnormและอื่น ๆ ใช้ไวยากรณ์คิวรีของตนเอง เอกสารเป็น ทางการมาก เขียนใน C. LT XML 2 อ้างว่ารองรับ XPath, XInclude และมาตรฐาน W3C อื่น ๆ

  • xmlgrep2 : การค้นหาที่ง่ายและทรงพลังด้วย XPath เขียนใน Perl โดยใช้ XML :: LibXML และ libxml2

  • XQSharp : รองรับ XQuery ซึ่งเป็นส่วนขยายของ XPath เขียนสำหรับ. NET Framework

  • xml-coreutils : ชุดเครื่องมือ Laird Breyer เทียบเท่ากับ GNU coreutils อภิปรายในเรียงความที่น่าสนใจเกี่ยวกับสิ่งที่เครื่องมือในอุดมคติควรมี

  • xmldiff : เครื่องมืออย่างง่ายสำหรับการเปรียบเทียบไฟล์ xml สองไฟล์

  • xmltk : ดูเหมือนจะไม่มีแพ็คเกจในเดเบียนอูบุนตู fedora หรือ macports ไม่มีการวางจำหน่ายมาตั้งแต่ปี 2550 และใช้การสร้างอัตโนมัติแบบพกพา

xml-coreutils ดูเหมือนว่าเป็นเอกสารที่ดีที่สุดและมุ่งเน้น UNIX เป็นส่วนใหญ่


1
คุณไม่สามารถสร้างสคริปต์ตัวห่อสำหรับโปรแกรม Ruby และส่งผ่านอาร์เรย์ของอาร์กิวเมนต์ในสคริปต์ไปยัง hpricot ได้หรือไม่ ตัวอย่างเช่นในเชลล์สคริปต์ PHP สิ่งต่อไปนี้ควรใช้ได้: <? php / path / to / hpricot $ argv?>
alastairs

25

ในรายการที่ยอดเยี่ยมของ Joseph Holsten ฉันเพิ่มสคริปต์บรรทัดคำสั่ง xpath ซึ่งมาพร้อมกับ Perl library XML :: XPath วิธีที่ยอดเยี่ยมในการดึงข้อมูลจากไฟล์ XML:

 xpath -q -e '/entry[@xml:lang="fr"]' *xml

3
นี่คือการติดตั้งโดยค่าเริ่มต้นใน osx แต่ไม่มี-q -eตัวเลือก ตัวอย่างรับค่าแอตทริบิวต์ "package" จากโหนด "manifest" ใน "AndroidManifest.xml":xpath AndroidManifest.xml 'string(/manifest/@package)' 2> /dev/null
antonj

25

นอกจากนี้ยังมีxml2และ2xmlจับคู่ มันจะช่วยให้เครื่องมือแก้ไขสตริงตามปกติในการประมวลผล XML

ตัวอย่าง. q.xml:

<?xml version="1.0"?>
<foo>
    text
    more text
    <textnode>ddd</textnode><textnode a="bv">dsss</textnode>
    <![CDATA[ asfdasdsa <foo> sdfsdfdsf <bar> ]]>
</foo>

xml2 < q.xml

/foo=
/foo=   text
/foo=   more text
/foo=   
/foo/textnode=ddd
/foo/textnode
/foo/textnode/@a=bv
/foo/textnode=dsss
/foo=
/foo=    asfdasdsa <foo> sdfsdfdsf <bar> 
/foo=

xml2 < q.xml | grep textnode | sed 's!/foo!/bar/baz!' | 2xml

<bar><baz><textnode>ddd</textnode><textnode a="bv">dsss</textnode></baz></bar>

PS นอกจากนี้ยังมี/html22html


@Joseph Holsten ใช่ อนุญาตให้แฮ็คกับ XML โดยไม่ต้องคิดอะไรผ่าน XPath
วิ

ดี! ฉันได้มุ่งเน้นไปที่เครื่องมือที่ไม่ได้ใช้รูปแบบสื่อกลาง แต่ความคิดเรื่องการแสดง xml เชิงเส้นที่มีความเที่ยงตรงสูงดูเหมือนจะเป็นวิธีที่ยอดเยี่ยมในการใช้ grep และ sed จริง ๆ คุณลอง pyxie แล้วหรือยัง มันเปรียบเทียบได้อย่างไร การเป็นตัวแทนสายอื่น ๆ ที่มุ่งเน้น? คุณจะพิจารณาสิ่งนี้ดีกว่าเพียงแค่แทนที่บรรทัดใหม่ xml ด้วยเอนทิตี (& # 10;) หรือไม่ สิ่งนี้จะช่วยให้คุณสามารถติดระเบียนในบรรทัดเดียวกันอย่างน้อย โอ้และคุณสามารถแก้ไขโพสต์ของคุณเพื่อรวมลิงค์ไปยังโครงการได้หรือไม่
โจเซฟโฮลสเตน

@Joseph Holsten ไม่ฉันไม่คิดว่ารูปแบบ pyxie จะมีประโยชน์มากกว่ารูปแบบ xml2 xml2 จัดเตรียม "เส้นทางแบบเต็ม" ในองค์ประกอบ XML ที่ซ้อนกันดังนั้นอนุญาตให้มีการจับคู่และการแทนที่บรรทัดที่เน้นมากขึ้น นอกจากนี้ยัง2xmlสามารถสร้าง XML จากxml2เอาต์พุตบางส่วน (กรอง) ได้อย่างง่ายดาย
วิ

5
+1 ฉันไม่สามารถโหวตได้เท่านี้ ... cat foo.xml | xml2 | grep /bar | 2xml- ให้โครงสร้างเดียวกันกับต้นฉบับ แต่องค์ประกอบทั้งหมดถูกถอดยกเว้นองค์ประกอบ "แถบ" น่ากลัว
mogsie

14

คุณสามารถใช้ xmllint:

xmllint --xpath //title books.xml

ควรรวมกับ distros ส่วนใหญ่และรวมกับ Cygwin ด้วย

$ xmllint --version
xmllint: using libxml version 20900

ดู:

$ xmllint
Usage : xmllint [options] XMLfiles ...
        Parse the XML files and output the result of the parsing
        --version : display the version of the XML library used
        --debug : dump a debug tree of the in-memory document
        ...
        --schematron schema : do validation against a schematron
        --sax1: use the old SAX1 interfaces for processing
        --sax: do not build a tree but work just at the SAX level
        --oldxml10: use XML-1.0 parsing rules before the 5th edition
        --xpath expr: evaluate the XPath expression, inply --noout

2
ไม่มี--xpathข้อโต้แย้งใด ๆxmllint: manpagez.com/man/1/xmllint
ตัวแปรที่สามารถเข้าใจได้

1
@MiserableVariable: หน้าคนไม่ถูกต้อง ฉันเพิ่งดู man page สำหรับเวอร์ชันของฉัน: อาร์กิวเมนต์ xpath ไม่อยู่ในรายการ นี่เป็นข้อผิดพลาดของเอกสาร ลองเรียกใช้โปรแกรมแทน
Dave Jarvis

2
@MiserableVariable --xpathเป็นนอกจากนี้ล่าสุดอย่างเป็นธรรมและไม่ได้อยู่ในเช่น RHEL 6 xmllintรุ่น
Daniel Beck

2
เพื่อให้แม่นยำยิ่งขึ้นxmllint --xpathได้รับการแนะนำใน libxml2 2.7.7 (ในปี 2010)
marbu

9

หากคุณกำลังมองหาโซลูชันบน Windows Powershell มีฟังก์ชันการทำงานในตัวสำหรับการอ่านและการเขียน XML

test.xml:

<root>
  <one>I like applesauce</one>
  <two>You sure bet I do!</two>
</root>

สคริปต์ PowerShell:

# load XML file into local variable and cast as XML type.
$doc = [xml](Get-Content ./test.xml)

$doc.root.one                                   #echoes "I like applesauce"
$doc.root.one = "Who doesn't like applesauce?"  #replace inner text of <one> node

# create new node...
$newNode = $doc.CreateElement("three")
$newNode.set_InnerText("And don't you forget it!")

# ...and position it in the hierarchy
$doc.root.AppendChild($newNode)

# write results to disk
$doc.save("./testNew.xml")

testNew.xml:

<root>
  <one>Who likes applesauce?</one>
  <two>You sure bet I do!</two>
  <three>And don't you forget it!</three>
</root>

ที่มา: /server/26976/update-xml-from-the-command-line-windows


ต่อสู้กับเครื่องมือ linux ต่างๆไม่กี่ชั่วโมงก่อนที่จะหันไปใช้ Powershell ฉันประหลาดใจที่มันยากมาก - linux cmd-line นั้นดีมากจริงๆ แต่ดูเหมือนว่าจะมีรูอยู่ที่นี่ หมายเหตุ: ใช้เคสสำหรับฉันคือ: 1) ค้นหาโหนดโดย xpath, 2) ลบหากพบ 3) เพิ่มโหนดใหม่ 4) บันทึกไฟล์ ฉันกำลังอัปเดตการตั้งค่าเครือข่ายจำนวนมาก หากใครรู้วิธีที่ง่าย / น่าเชื่อถือในการทำเช่นนี้ฉันหูของทุกคน
Richard Hauer

ว้าวสิ่งนี้จะทำให้เขยิบไปจนถึงแนวของทางออกที่ยอมรับได้ แต่โดยสุจริตฉันอาจยอมรับถ้ามันดูเหมือนxps $doc .root.one xps $doc 'AppendChild("three")'และxps $doc '.three.set_InnerText("And don't you forget it!")'ซึ่งด้อยกว่าอย่างชัดเจน!
Joseph Holsten


6

ขึ้นอยู่กับสิ่งที่คุณต้องการทำ

XSLT อาจเป็นหนทางไป แต่มีช่วงการเรียนรู้ ลองxsltprocและสังเกตว่าคุณสามารถส่งพารามิเตอร์ได้


4

นอกจากนี้ยังมีsaxon-lintจากบรรทัดคำสั่งที่มีความสามารถในการใช้ XPath 3.0 / XQuery 3.0 (เครื่องมือบรรทัดคำสั่งอื่น ๆ ใช้ XPath 1.0)

ตัวอย่าง :

http / html:

$ saxon-lint --html --xpath 'count(//a)' http://stackoverflow.com/q/91791
328

xml:

$ saxon-lint --xpath '//a[@class="x"]' file.xml

4

D. Bohdan ดำรงตำแหน่ง GitHub repo แบบโอเพนซอร์สที่เก็บรายการเครื่องมือบรรทัดคำสั่งสำหรับเครื่องมือข้อความที่มีโครงสร้างมีส่วนสำหรับเครื่องมือ XML / HTML:

https://github.com/dbohdan/structured-text-tools#xml-html


3

XQuery อาจเป็นทางออกที่ดี มันค่อนข้างง่ายต่อการเรียนรู้และเป็นมาตรฐาน W3C

ฉันจะแนะนำXQSharpสำหรับโปรเซสเซอร์บรรทัดคำสั่ง


1
BaseX ยังมีตัวประมวลผลบรรทัดคำสั่ง XQuery (นอกเหนือจากโหมดฐานข้อมูล) และยังคงอยู่กับเวอร์ชันมาตรฐานแบบทันสมัย ​​(ตามแบบร่างวิวัฒนาการของ XQuery 3.0 อย่างใกล้ชิด)
Charles Duffy

3

ฉันใช้xmlstarletเป็นครั้งแรกและยังคงใช้อยู่ เมื่อข้อความค้นหายากฉันต้องการxpath2และxqueryของ XML ฉันต้องการการสนับสนุนฉันหันไปหาxidel http://www.videlibri.de/xidel.html


1

Grep เทียบเท่า

คุณสามารถกำหนดฟังก์ชั่นทุบตีพูดว่า "xp" ("xpath") ที่ล้อมรอบโค้ดไพ ธ อน 3 ในการใช้งานคุณจะต้องติดตั้ง python3 และ python-lxml ประโยชน์ที่ได้รับ:

  1. การจับคู่ regex ที่คุณขาดเช่น xmllint
  2. ใช้เป็นตัวกรอง (ในไพพ์) บน commandline

ใช้งานง่ายและทรงพลังเช่นนี้:

xmldoc=$(cat <<EOF
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
EOF
)
selection='//*[namespace-uri()="http://www.sample.com/" and local-name()="job" and re:test(.,"^pro.*ing$")]/text()'
echo "$xmldoc" | xp "$selection"
# prints programming

xp () มีลักษณะดังนี้:

xp()
{ 
local selection="$1";
local xmldoc;
if ! [[ -t 0 ]]; then
    read -rd '' xmldoc;
else
    xmldoc="$2";
fi;
python3 <(printf '%b' "from lxml.html import tostring\nfrom lxml import etree\nfrom sys import stdin\nregexpNS = \"http://exslt.org/regular-expressions\"\ntree = etree.parse(stdin)\nfor e in tree.xpath('""$selection""', namespaces={'re':regexpNS}):\n  if isinstance(e, str):\n    print(e)\n  else:\n    print(tostring(e).decode('UTF-8'))") <<< "$xmldoc"
}

เทียบเท่าซีดาน

พิจารณาใช้ xq ซึ่งให้พลังเต็มที่ของ jq "ภาษาโปรแกรม" หากคุณติดตั้ง python-pip คุณสามารถติดตั้ง xq ด้วย pip install yqจากนั้นในตัวอย่างด้านล่างเราจะแทนที่ "Keep Accounts" ด้วย "Keep Accounts 2":

xmldoc=$(cat <<'EOF'
<resources>
    <string name="app_name">Keep Accounts</string>
    <string name="login">"login"</string>
    <string name="login_password">"password:"</string>
    <string name="login_account_hint">input to login</string>
    <string name="login_password_hint">input your password</string>
    <string name="login_fail">login failed</string>
</resources>
EOF
)
echo "$xmldoc" | xq '.resources.string = ([.resources.string[]|select(."#text" == "Keep Accounts") ."#text" = "Keep Accounts 2"])' -x

-1

JEdit มีปลั๊กอินที่เรียกว่า "XQuery" ซึ่งมีฟังก์ชันการสืบค้นสำหรับเอกสาร XML

ไม่ใช่บรรทัดคำสั่ง แต่ใช้งานได้!


ในขณะที่ jedit grep(1)จะมีวิธีการที่จะค้นหาผ่านแฟ้มที่ไม่ได้ทำให้มันเป็นคู่แข่ง
Joseph Holsten
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.