Ja už na Python, Javu a pod. nemám nervy.
import groovy.xml.XmlSlurper
def data = '''<?xml version="1.0" encoding="utf-8"?>
<products>
<product>
<id>1</id>
<name>Product A</name>
<price>780</price>
</product>
<product>
<id>2</id>
<name>Product B</name>
<price>1100</price>
</product>
<product>
<id>3</id>
<name>Product C</name>
<price>1050</price>
</product>
<product>
<id>4</id>
<name>Product D</name>
<price>950</price>
</product>
</products>
'''
def products = new XmlSlurper().parseText(data)
def id1 = products.product[0].id
def name1 = products.product[0].name
def price1 = products.product[0].price
println "$id1 $name1 $price1"
def names = products.'**'.findAll { node -> node.name() == 'name' }*.text()
println names
def prices = products.product.'*'.find { node ->
node.name() == 'price' && node.text() as Integer < 1000
}
println prices
F# má tiež parádne riešenie.
Akonáhle človek raz vyskúša expresívne jazyky ako F#, Clojure, či Groovy, tak už viac nechce ísť naspäť do tuctových jazykov.
#r "nuget: FSharp.Data"
open FSharp.Data
open System
[<Literal>]
let data = """<?xml version="1.0" encoding="utf-8"?>
<products>
<product>
<id>1</id>
<name>Product A</name>
<price>780</price>
</product>
<product>
<id>2</id>
<name>Product B</name>
<price>1100</price>
</product>
<product>
<id>3</id>
<name>Product C</name>
<price>1050</price>
</product>
<product>
<id>4</id>
<name>Product D</name>
<price>950</price>
</product>
</products>
"""
type xml = XmlProvider<data>
let d = xml.GetSample().Products
d |> Seq.iter (fun p -> Console.WriteLine($"{p.Name} {p.Price}"))
let res = d |> Seq.filter (fun p -> p.Price < 1000)
for v in res do
Console.WriteLine v
printfn "%A" d[..2]
Výstup:
$ fsx parse.fsx
Product A 780
Product B 1100
Product C 1050
Product D 950
<product>
<id>1</id>
<name>Product A</name>
<price>780</price>
</product>
<product>
<id>4</id>
<name>Product D</name>
<price>950</price>
</product>
[|<product>
<id>1</id>
<name>Product A</name>
<price>780</price>
</product>;
<product>
<id>2</id>
<name>Product B</name>
<price>1100</price>
</product>;
<product>
<id>3</id>
<name>Product C</name>
<price>1050</price>
</product>|]
lxml umi take nacist xml do objektu, kte jsou tagy atributy, ale je to mene obecne
from lxml import objectify
data = b'''<?xml version="1.0" encoding="utf-8"?>
<products>
<product>
<id>1</id>
<name>Product A</name>
<price>780</price>
</product>
<product>
<id>2</id>
<name>Product B</name>
<price>1100</price>
</product>
<product>
<id>3</id>
<name>Product C</name>
<price>1050</price>
</product>
<product>
<id>4</id>
<name>Product D</name>
<price>950</price>
</product>
</products>
'''
products = objectify.fromstring(data)
p = products.product[0]
print(p.id, p.name, p.price)
names = [p.name for p in products.product]
print(names)
prices = [p.price for p in products.product if int(p.price) < 1000]
print(prices)21. 2. 2022, 13:52 editováno autorem komentáře
Zkoušel jsem to právě na pom.xml, které má default namespace (xmlns) a ElementTree udělá všechny tagy právě s tím namespace. Takže místo tagu dependency je název tagu {namespace}dependency takže ho z toho bez namespace nedostanete a u XPath musíte buď psát {*} u každého tagu nebo dát namespace jako parametr. Tohle mi přijde naprosto nepoužitelné a navíc ElementTree neumí ten namespace z elementu získat, takže když ho nechcete hardcode (což asi nikdo nechce), tak to z toho názvu tagu musíte vyparsovat. Proto se ptám zda lxml umí ten default namespace "ignorovat".