XML Komut Satırı İşleme için Grep ve Sed Eşdeğeri


147

Kabuk komut dosyası oluştururken, tipik olarak veriler csv gibi tek satırlık kayıt dosyalarında olacaktır. Bu verileri grepve ile işlemek gerçekten çok basit sed. Ancak XML ile sık sık uğraşmam gerekiyor, bu yüzden o XML verilerine komut satırı aracılığıyla komut dosyası erişimi sağlamanın bir yolunu gerçekten istiyorum. En iyi araçlar nelerdir?


xml_grep grepleme için uygundur, stackoverflow.com/a/2222224/871134
Deleplace

Yanıtlar:


105

Xmlstarlet'i bu tür şeylerde oldukça iyi buldum.

http://xmlstar.sourceforge.net/

Çoğu dağıtım deposunda da bulunmalıdır. Giriş öğretici burada:

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


1
Sourceforge sitesinde Windows ikili dosyaları bulunduğunu belirtmek istedim.
Steve Bennett

Anladığım kadarıyla XQuery'yi desteklemiyor.
Steve Bennett

@SteveBennett gerçekten öyle değil, ancak ham XPath'e eklediği özellikler onu "grep ve sed" ile rekabet edebilecek kadar iyi. XQuery'nin süslü, süslü iyiliğini istiyorsanız ... bu daha çok perl veya awk'ye eşdeğer bir XML gibidir. :)
Charles Duffy

36

Bazı umut verici araçlar:

  • Nokogiri : ayrıştırma HTML / XML DOMs yakut XPath & CSS seçicileri kullanarak

  • hpricot : kullanımdan kaldırıldı

  • fxgrep : Belgeleri sorgulamak için kendi XPath benzeri sözdizimini kullanır. SML'de yazıldığından kurulum zor olabilir.

  • LT XML : SGML dahil araçları, elde edilen XML aracıdır sggrep, sgsort, xmlnormve diğerleri. Kendi sorgu sözdizimini kullanır. Belgeler çok resmidir. C. LT XML 2'de yazılmıştır. XPath, XInclude ve diğer W3C standartları desteklendiğini iddia etmektedir.

  • xmlgrep2 : XPath ile basit ve güçlü arama. XML :: LibXML ve libxml2 kullanılarak Perl'de yazılmıştır.

  • XQSharp : XPath'in uzantısı olan XQuery'yi destekler. .NET Framework için yazılmıştır.

  • xml-coreutils : Laird Breyer'in araç seti GNU coreutils'e eşdeğerdir. İdeal araç setinin neleri içermesi gerektiğine dair ilginç bir makalede tartışıldı .

  • xmldiff : İki xml dosyasını karşılaştırmak için basit bir araç.

  • xmltk : debian, ubuntu, fedora veya macports'ta pakete sahip görünmüyor, 2007'den beri bir sürümü yok ve taşınabilir olmayan yapı otomasyonu kullanıyor.

xml-coreutils, en iyi belgelenmiş ve en çok UNIX odaklı görünüyor.


1
Ruby programı için bir sarmalayıcı komut dosyası oluşturup, komut dosyasındaki argümanlar dizisini hpricot'a iletemez misiniz? Örneğin, bir PHP kabuk betiğinde, aşağıdakine benzer bir şey çalışmalıdır: <? Php / path / to / hpricot $ argv?>
alastairs

25

Joseph Holsten'in mükemmel listesine Perl kütüphanesi XML :: XPath ile gelen xpath komut satırı betiğini ekliyorum. XML dosyalarından bilgi almanın harika bir yolu:

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

3
Bu, varsayılan olarak osx'te kurulur, ancak -q -eseçenekler olmadan . Örnek, "AndroidManifest.xml" deki "manifest" düğümünden "paket" özniteliği değerini alın:xpath AndroidManifest.xml 'string(/manifest/@package)' 2> /dev/null
antonj

25

Orada da xml2ve 2xmlçift. Normal dize düzenleme araçlarının XML'i işlemesine izin verir.

Misal. 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 Ayrıca html2/ vardır 2html.


@Joseph Holsten Evet. XPath şeylerini düşünmeden XML ile hacklemeye izin verir.
Vi.

Güzel! Ara format kullanmayan araçlara odaklanıyordum, ancak xml'nin yüksek kaliteli, satır odaklı temsili fikri gerçek grep ve sed'i kullanmaya devam etmenin harika bir yolu gibi görünüyor. Pyxie'yi denedin mi? Nasıl karşılaştırılır? Başka hat odaklı temsiller var mı? Bunu, xml yeni satırlarını bir varlık (& # 10;) ile değiştirmekten daha mı iyi düşünüyorsunuz? Bu, kayıtları en azından aynı satıra yapıştırmanıza izin verir. Oh, ve projeye bir bağlantı eklemek için gönderinizi düzenleyebilir misiniz?
Joseph Holsten

@Joseph Holsten Hayır, pyxie formatının xml2 formatından daha kullanışlı olacağını düşünmüyorum. xml2, iç içe geçmiş XML öğelerinde "tam yol" sağlar, bu nedenle daha satır odaklı eşleştirme ve değiştirmeye izin verir. Ayrıca 2xmlXML'i kısmi (filtrelenmiş) xml2çıktıdan kolayca yeniden oluşturabilir .
Vi.

5
+1 Buna yeteri kadar oy veremiyorum ... cat foo.xml | xml2 | grep /bar | 2xml- size orijinaliyle aynı yapıyı verir, ancak "çubuk" öğeleri dışında tüm öğeler çıkarılmıştır. Harika.
mogsie

14

Xmllint'i kullanabilirsiniz:

xmllint --xpath //title books.xml

Çoğu dağıtımla birlikte paketlenmelidir ve ayrıca Cygwin ile birlikte gelir.

$ xmllint --version
xmllint: using libxml version 20900

Görmek:

$ 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
Hiçbir yoktur --xpathargüman xmllint: manpagez.com/man/1/xmllint
Sefil Değişken

1
@MiserableVariable: Kılavuz sayfası yanlış. Sürümüm için man sayfasına baktım: xpath argümanı listelenmemiş. Bu bir dokümantasyon hatasıdır. Bunun yerine programı çalıştırmayı deneyin.
Dave Jarvis

2
@MiserableVariable --xpatholdukça yeni bir eklemedir ve örneğin RHEL 6 sürümlerinde değil xmllint.
Daniel Beck

2
Daha doğrusu xmllint --xpathlibxml2 2.7.7'de (2010'da) tanıtıldı.
marbu

9

Windows'ta bir çözüm arıyorsanız Powershell, XML okumak ve yazmak için yerleşik işlevselliğe sahiptir.

test.xml:

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

Powershell betiği:

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

Kaynak: /server/26976/update-xml-from-the-command-line-windows


Powershell'e başvurmadan önce birkaç saat boyunca çeşitli linux araçlarıyla savaştı. Bunun bu kadar zor olmasına şaşırdım - linux cmd-line normalde gerçekten iyi ama burada bir boşluk var gibi görünüyor. Not: Benim için kullanım durumu şuydu: 1) xpath ile düğümleri bulun, 2) bulunursa kaldırın, 3) yeni düğümler ekleyin, 4) dosyayı kaydedin. Bir grup solr yapılandırmasını güncelliyordum. Bunu yapmanın kolay / güvenilir bir yolunu bilen varsa çok dinliyorum
Richard Hauer

Vay canına, bu gerçekten de kabul edilebilir bir çözüm çizgisine kadar uyuyor. Ama dürüst olmak gerekirse, eğer böyle görünseydi muhtemelen kabul ederim xps $doc .root.one xps $doc 'AppendChild("three")'ve xps $doc '.three.set_InnerText("And don't you forget it!")'ki bu açıkça aşağılıktır!
Joseph Holsten


6

Tam olarak ne yapmak istediğinize bağlı.

XSLT gidecek yol olabilir, ancak bir öğrenme eğrisi var. Xsltproc'u deneyin ve parametreleri verebileceğinizi unutmayın.


4

saxon-lintXPath 3.0 / XQuery 3.0 kullanma becerisine sahip komut satırından da var . (Diğer komut satırı araçları XPath 1.0 kullanır).

ÖRNEKLER:

http / html:

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

xml:

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


3

XQuery iyi bir çözüm olabilir. Öğrenmesi (nispeten) kolaydır ve bir W3C standardıdır.

Bir komut satırı işlemcisi için XQSharp'ı öneririm .


1
BaseX ayrıca bir komut satırı XQuery işlemcisine (veritabanı moduna ek olarak) sahiptir ve standardın son teknoloji sürümleriyle güncel kalır (XQuery 3.0'ın gelişen taslağını oldukça yakından takip ederek).
Charles Duffy


1

Grep Eşdeğeri

Bazı python3 kodunu saran "xp" ("xpath") gibi bir bash işlevi tanımlayabilirsiniz. Kullanmak için python3 ve python-lxml yüklemeniz gerekir. Faydaları:

  1. örneğin xmllint'te eksik olan normal ifade eşleşmesi.
  2. Komut satırında filtre olarak (boru içinde) kullanın

Bunun gibi kullanımı kolay ve güçlü:

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 () şuna benzer:

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"
}

Sed Eşdeğeri

Size jq "programlama dilinin" tam gücünü veren xq kullanmayı düşünün. Eğer python-pip yüklediyseniz, xq'yi pip install yq ile kurabilirsiniz , ardından aşağıdaki örnekte "Hesapları Sakla" "Hesapları Sakla 2" ile değiştiriyoruz:

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, XML belgeleri için sorgulama işlevi sağlayan "XQuery" adlı bir eklentiye sahiptir.

Tam olarak komut satırı değil, ama işe yarıyor!


JEdit'in bir dosyada arama yapmanın bir yolu olması muhtemel olsa da, bu onu rakip yapmaz grep(1).
Joseph Holsten
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.