XML split naar meerdere files

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • smeerbartje
  • Registratie: September 2006
  • Laatst online: 29-09 09:17
Ik heb een XML file, laten we zeggen de volgende:

code:
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
<?xml version="1.0" encoding="utf-8" ?>
<books>
    <book>
        <code></code>
        <text></text>
    </book>
    <book>
        <code></code>
        <text></text>
    </book>
    <book>
        <code></code>
        <text></text>
    </book>
    <book>
        <code></code>
        <text></text>
    </book>
    <book>
        <code></code>
        <text></text>
    </book>
    <book>
        <code></code>
        <text></text>
    </book>
</books>


Nu wil ik ik met een bash script het volgende bereiken:
1. Chunken van de file naar kleine XML files
2. En dan per XML file ongeveer 'x' aantal books

Ik heb lopen kloten met sed, awd, sgrep, etc. en mij meest "in de buurt"-komende script is het volgende:

code:
1
sgrep -d -o "XXXSTART%rSTOPXXX" '"<book>" .. "</book>"' input.xml | sed -e 's/XXXSTART/<books>/g;s/STOPXXX/<\/books>/g'


Alleen deze zet dus effectief om elk boek een <books>-tag. Wie kan me even in de goede richting duwen? M'n huidige output is:

code:
1
2
3
4
5
6
7
8
9
<books><book>
        <code></code>
        <text></text>
    </book></books><books><book>
        <code></code>
        <text></text>
    </book></books><books><book>
    <titel>hier</title>
  </book></books>

[ Voor 10% gewijzigd door smeerbartje op 04-07-2014 14:13 ]


Acties:
  • 0 Henk 'm!

  • Mijzelf
  • Registratie: September 2004
  • Niet online
Bash:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/sh

file=1
exec >/dev/null

while read line
do
        if [ "$line" = "<book>" ] ; then
                exec >${1}${file}
                let file=file+1
                echo "<?xml version="1.0" encoding="utf-8" ?>"
                echo "<books>"
        fi

        echo $line

        if [ "$line" = "</book>" ] ; then
                echo "</books>"
                exec >/dev/null
        fi
done
code:
1
script outputfile <inputfile

Acties:
  • 0 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 22:15
XML processen als text strings is geen goed idee. Als bijvoorbeeld de insignificante whitespace veranderd werkt je script niet meer.

Je kan in een bash script wel werken met bijvoorbeeld xmlstarlet:
Aantal books:
COUNT=`xmlstarlet select --text --template --value-of "count(/books/book)" books.xml`

Hier kan je in bash een for loopje van maken en dan book element BEGIN t/m END selecteren:
xmlstarlet select --template --elem books --copy-of "/books/book[position() >= $BEGIN and position() <= $END]" books.xml


Als je dan toch XML als text gaat processen doe dan eerst een "xmlstarlet format", of zet het om naar pyx of xml2 formaat die zijn gemaakt voor scripting.