XML | Alle subnodes selecteren met de hoofdnode erbij

Pagina: 1
Acties:

Vraag


  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 02-10 14:45

Yagermeister

Bedrijfsprutser on call

Topicstarter
Mijn vraag

Voor een script krijgen wij een file met daarin een een hele hoop XML tekst. Een voorbeeld hiervan is hieronder.

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<searchresults>
  <success>true</success>
  <data>
    <idpurchaseorder>373251</idpurchaseorder>
    <idsupplier>42919</idsupplier>
    <idwarehouse>4863</idwarehouse>
    <idtemplate>3994</idtemplate>
    <purchaseorderid>PO2019-1008</purchaseorderid>
    <supplier_orderid>09-09-2019</supplier_orderid>
    <supplier_name></supplier_name>
    <status>purchased</status>
    <products>
      <idpurchaseorder_product>5275880</idpurchaseorder_product>
      <idproduct>10307107</idproduct>
      <productcode>P00019664</productcode>
      <productcode_supplier>0389450893456</productcode_supplier>
      <name>Unold 78856</name>
      <price>99</price>
      <amount>1</amount>
      <amountreceived>0</amountreceived>
    </products>
  </data>
  <data>
    <idpurchaseorder>373062</idpurchaseorder>
    <idsupplier>42561</idsupplier>
    <idwarehouse>4863</idwarehouse>
    <idtemplate>3994</idtemplate>
    <purchaseorderid>PO2019-1007</purchaseorderid>
    <supplier_orderid>09-09-2019</supplier_orderid>
    <supplier_name></supplier_name>
    <status>purchased</status>
    <products>
      <idpurchaseorder_product>5272744</idpurchaseorder_product>
      <idproduct>10304708</idproduct>
      <productcode>P00172393</productcode>
      <productcode_supplier>34556WDR09</productcode_supplier>
      <name>Product 2</name>
      <price>999</price>
      <amount>1</amount>
      <amountreceived>0</amountreceived>
    </products>
    <products>
      <idpurchaseorder_product>5272745</idpurchaseorder_product>
      <idproduct>10304135</idproduct>
      <productcode>P00020201</productcode>
      <productcode_supplier>345345074</productcode_supplier>
      <name>Productname</name>
      <price>99</price>
      <amount>1</amount>
      <amountreceived>0</amountreceived>
    </products>
  </data>
 </searchresults>


Van deze file wil ik de volgende gegevens hebben:

code:
1
idpurchaseorder;idsupplier;purchaseorderid;idproduct;productcode;price;amount;amountreceived


Wat ik geprobeerd heb met XMLstarlet is het volgende (ik heb even alleen idpurchaseorder en idproduct gebruikt voor de leesbaarheid).

code:
1
xmlstarlet sel -t -m //searchresults/data -v "concat(idpurchaseorder,';',products/idproduct)" -n purchaseorders.xml


De uitkomst hiervan was:

code:
1
2
373251;10307107
373062;10304708


Dit klopt natuurlijk niet aangezien het 2de product niet erbij staat


Met wat aanpassingen bij xmlstarlet:
code:
1
xmlstarlet sel -t -m //searchresults/data -v idpurchaseorder -o ";" -v products/idproduct -n purchaseorders.xml


Dit bracht me al korter in de buurt namelijk:

code:
1
2
3
373251;10307107
373062;10304708
10304135


Hier heb ik wel het 2de product echter heb ik niet de purchaseorderid erbij staan. Wat ik verwacht is onderstaande:

code:
1
2
3
373251;10307107
373062;10304708
373062;10304135



Met wat zoeken heb ik uitgevonden dat ik de subnodes als eerste moet selecteren echter snap ik niet hoe ik daarna de hoofdnode per regel kan toevoegen.

Ik kan wel met omwegen aan alle data komen maar dat is natuurlijk weer onhandig aangezien het ook met xmlstarlet moet kunnen. Ik heb echter al de hele dag zitten puzzelen maar ik zie niet wat ik fout doe of wat ik moet aanpassen. ;(

-Te huur

Beste antwoord (via Yagermeister op 11-09-2019 16:49)


  • Jivebunny
  • Registratie: November 2010
  • Niet online

Jivebunny

Fail to plan. Plan to fail.

Werkt dit? Bij mij wel met kopie van jouw bestandje (en nog wat meer uitdagingen erin gebouwd zoals een purchaseorderid met 3+ producten):

code:
1
xmlstarlet sel -T -t -m "/searchresults/data/products" -v ../idpurchaseorder -o ; -v ../idsupplier -o ; -v ../purchaseorderid -o ; -v idproduct -o ; -v productcode -o ; -v price -o ; -v amount -o ; -v amountreceived -n purchaseorders.xml


Het strookt in ieder geval met mijn eerste opmerking: Je wil het idproduct als basis selecteren/matchen, dan heb je alle gevallen te pakken. In deze oplossing ga je met ../ weer terug omhoog en zoek je naar de siblings van <products>. Het startpunt ligt dan ook 1 dieper dan je originele aanpak.

[ Voor 27% gewijzigd door Jivebunny op 11-09-2019 16:33 . Reden: Uitleg ]

Pixel 9 Pro XL | NAS: HP Gen8 e3-1265L v2 16GB 12TB unRAID 6.9.2 | D: Ryzen 5600x 16GB 3000mhz RX 6800 XT MB Acer 27" IPS 144hz | Suzuki Swift 1.2 (2013)

Alle reacties


  • Jivebunny
  • Registratie: November 2010
  • Niet online

Jivebunny

Fail to plan. Plan to fail.

code:
1
xmlstarlet sel -t --var idpurchaseorder=//searchresults/data/idpurchaseorder -m "//*[idproduct]" -v "concat($idpurchaseorder,';',.//idproduct)" -n purchaseorders.xml


Omdat je een purchaseorder (parent node) hebt, met mogelijk multiple child-nodes van hetzelfde element, moet je bottom up selecteren en de parent erbij trekken via een variabele. Je huidige benadering is top-down. Zodra er geen nieuwe idpurchaseorders meer zijn, stopt ie, en dus heb je alleen het eerste child. Jouw andere poging kwam al verder, maar printte niet de parent-node id.

Deze oplossing wel. Je kan zelf in de concat functie de overige waarden erbij roepen. Succes.
Edit: Moet nog even sleutelen, idpurchaseorder is niet juist

[ Voor 61% gewijzigd door Jivebunny op 11-09-2019 13:34 . Reden: klopt helaas toch niet ]

Pixel 9 Pro XL | NAS: HP Gen8 e3-1265L v2 16GB 12TB unRAID 6.9.2 | D: Ryzen 5600x 16GB 3000mhz RX 6800 XT MB Acer 27" IPS 144hz | Suzuki Swift 1.2 (2013)


  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 02-10 14:45

Yagermeister

Bedrijfsprutser on call

Topicstarter
Jivebunny schreef op woensdag 11 september 2019 @ 13:02:
code:
1
xmlstarlet sel -t --var idpurchaseorder=//searchresults/data/idpurchaseorder -m "//*[idproduct]" -v "concat($idpurchaseorder,';',.//idproduct)" -n purchaseorders.xml


Omdat je een purchaseorder (parent node) hebt, met mogelijk multiple child-nodes van hetzelfde element, moet je bottom up selecteren en de parent erbij trekken via een variabele. Je huidige benadering is top-down. Zodra er geen nieuwe idpurchaseorders meer zijn, stopt ie, en dus heb je alleen het eerste child. Jouw andere poging kwam al verder, maar printte niet de parent-node id.

Deze oplossing wel. Je kan zelf in de concat functie de overige waarden erbij roepen. Succes.
Edit: Moet nog even sleutelen, idpurchaseorder is niet juist
Alvast bedankt maar zoals je zelf ook al hebt ondervonden werkt die helaas niet.

Ik krijg de volgende foutmelding overigens:

code:
1
2
3
Invalid expression: concat(,';',.//idproduct)
compilation error: element with-param
XSLT-with-param: Failed to compile select expression 'concat(,';',.//idproduct)'


Ik had mijn gedachten even over de regel laten gaan maar aangezien die niet werkt denk ik niet dat het veel nut heeft om deze proberen uit te leggen natuurlijk :)

-Te huur


  • Jivebunny
  • Registratie: November 2010
  • Niet online

Jivebunny

Fail to plan. Plan to fail.

Denk dat je via xslt wel makkelijker je lijstje kan genereren overigens. Nog even zoekende. Krijg met xmlstarlet het navigeren door de nodestructuur niet zo dat ik naar de ancestor kom bij het afdrukken hehe. Met xslt heb je zo een for-each gebouwd. Je kan overigens wel zag ik, niet getest, een xslt template over je data laten gaan met xmlstarlet, dus dat is nog een richting. Weet niet hoe je het precies wil inzetten?

Pixel 9 Pro XL | NAS: HP Gen8 e3-1265L v2 16GB 12TB unRAID 6.9.2 | D: Ryzen 5600x 16GB 3000mhz RX 6800 XT MB Acer 27" IPS 144hz | Suzuki Swift 1.2 (2013)


Acties:
  • +1 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 02-10 14:45

Yagermeister

Bedrijfsprutser on call

Topicstarter
Jivebunny schreef op woensdag 11 september 2019 @ 14:36:
Denk dat je via xslt wel makkelijker je lijstje kan genereren overigens. Nog even zoekende. Krijg met xmlstarlet het navigeren door de nodestructuur niet zo dat ik naar de ancestor kom bij het afdrukken hehe. Met xslt heb je zo een for-each gebouwd. Je kan overigens wel zag ik, niet getest, een xslt template over je data laten gaan met xmlstarlet, dus dat is nog een richting. Weet niet hoe je het precies wil inzetten?
Het enigste wat ik eigenlijk wil is een csv eruit krijgen met de data die ik nodig heb. Hoe en waar ik aan die data kom is verder niet van belang. Ik heb eigenlijk alleen een beetje ervaring met xmlstarlet. Helaas heb ik van xslt geen kennis om hier iets kundigs van te maken.

-Te huur


Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • Jivebunny
  • Registratie: November 2010
  • Niet online

Jivebunny

Fail to plan. Plan to fail.

Werkt dit? Bij mij wel met kopie van jouw bestandje (en nog wat meer uitdagingen erin gebouwd zoals een purchaseorderid met 3+ producten):

code:
1
xmlstarlet sel -T -t -m "/searchresults/data/products" -v ../idpurchaseorder -o ; -v ../idsupplier -o ; -v ../purchaseorderid -o ; -v idproduct -o ; -v productcode -o ; -v price -o ; -v amount -o ; -v amountreceived -n purchaseorders.xml


Het strookt in ieder geval met mijn eerste opmerking: Je wil het idproduct als basis selecteren/matchen, dan heb je alle gevallen te pakken. In deze oplossing ga je met ../ weer terug omhoog en zoek je naar de siblings van <products>. Het startpunt ligt dan ook 1 dieper dan je originele aanpak.

[ Voor 27% gewijzigd door Jivebunny op 11-09-2019 16:33 . Reden: Uitleg ]

Pixel 9 Pro XL | NAS: HP Gen8 e3-1265L v2 16GB 12TB unRAID 6.9.2 | D: Ryzen 5600x 16GB 3000mhz RX 6800 XT MB Acer 27" IPS 144hz | Suzuki Swift 1.2 (2013)


Acties:
  • +1 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 02-10 14:45

Yagermeister

Bedrijfsprutser on call

Topicstarter
Jivebunny schreef op woensdag 11 september 2019 @ 16:21:
Werkt dit? Bij mij wel met kopie van jouw bestandje (en nog wat meer uitdagingen erin gebouwd zoals een purchaseorderid met 3+ producten):

code:
1
xmlstarlet sel -T -t -m "/searchresults/data/products" -v ../idpurchaseorder -o ; -v ../idsupplier -o ; -v ../purchaseorderid -o ; -v idproduct -o ; -v productcode -o ; -v price -o ; -v amount -o ; -v amountreceived -n purchaseorders.xml


Het strookt in ieder geval met mijn eerste opmerking: Je wil het idproduct als basis selecteren/matchen, dan heb je alle gevallen te pakken. In deze oplossing ga je met ../ weer terug omhoog en zoek je naar de siblings van <products>. Het startpunt ligt dan ook 1 dieper dan je originele aanpak.
Ik heb het even snel bekeken en ik kreeg eerst een foutmelding. Doordat ik ZSH als shell gebruik heeft die een hekel aan ; dus ik heb er onderstaande van gemaakt.

code:
1
xmlstarlet sel -T -t -m "/searchresults/data/products" -v ../idpurchaseorder -o ";" -v ../idsupplier -o ";" -v ../purchaseorderid -o ";" -v idproduct -o ";" -v productcode -o ";" -v price -o ";" -v amount -o ";" -v amountreceived -n purchaseorders.xml


En dit heeft gewerkt! Nu krijg ik alle gewenste data terug. Een beetje stom is wel dat ik gisteren ook nog met ../ geprobeerd heb en dit niet werkte |:(

-Te huur


Acties:
  • +1 Henk 'm!

  • Jivebunny
  • Registratie: November 2010
  • Niet online

Jivebunny

Fail to plan. Plan to fail.

Yagermeister schreef op woensdag 11 september 2019 @ 16:57:
[...]


Ik heb het even snel bekeken en ik kreeg eerst een foutmelding. Doordat ik ZSH als shell gebruik heeft die een hekel aan ; dus ik heb er onderstaande van gemaakt.
Ah ik zat op werk met een windows omgeving dus helaas cmd-prompt haha.
Yagermeister schreef op woensdag 11 september 2019 @ 16:57:
[...]

code:
1
xmlstarlet sel -T -t -m "/searchresults/data/products" -v ../idpurchaseorder -o ";" -v ../idsupplier -o ";" -v ../purchaseorderid -o ";" -v idproduct -o ";" -v productcode -o ";" -v price -o ";" -v amount -o ";" -v amountreceived -n purchaseorders.xml


En dit heeft gewerkt! Nu krijg ik alle gewenste data terug. Een beetje stom is wel dat ik gisteren ook nog met ../ geprobeerd heb en dit niet werkte |:(
Ik had toenstraks ook al met ../ geprobeerd, maar de deze functionaliteit binnen een -v concat() gaat dus helemaal mis hehe.

Had even een ingeving en even een momentje de tijd.

Pixel 9 Pro XL | NAS: HP Gen8 e3-1265L v2 16GB 12TB unRAID 6.9.2 | D: Ryzen 5600x 16GB 3000mhz RX 6800 XT MB Acer 27" IPS 144hz | Suzuki Swift 1.2 (2013)


Acties:
  • +1 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 02-10 14:45

Yagermeister

Bedrijfsprutser on call

Topicstarter
Jivebunny schreef op woensdag 11 september 2019 @ 17:02:
[...]


Ah ik zat op werk met een windows omgeving dus helaas cmd-prompt haha.


[...]


Ik had toenstraks ook al met ../ geprobeerd, maar de deze functionaliteit binnen een -v concat() gaat dus helemaal mis hehe.

Had even een ingeving en even een momentje de tijd.
Ik vergeet het ook steeds dat ik het moet aanpassen. Ik ben in ieder geval super blij dat ik het werkend heb. Met wat aanpassingen in de benamingen heb ik het ook voor een andere xml kunnen gebruiken dus ik kan weer gelukkig verder knutselen :)

-Te huur

Pagina: 1