Plik XML wygląda tak:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE lista.kompozycji SYSTEM "lkompc.dtd" > <lista.kompozycji> <kompozycja typ="i.orkiestro"> <tytul>Atlantyda I na orkiestrę symfoniczną</tytul> <xsklad>4 akordeony w orkiestrze</xsklad> <autor> <nazwisko>Augustyn</nazwisko> <imie>Rafał</imie> </autor> <rok>1979</rok> <sklad>4 acc</sklad> <wydawca>manus</wydawca> </kompozycja> ... <kompozycja typ="solo"> <tytul>Rapsodia</tytul> <xsklad>akordeon solo</xsklad> <autor> <nazwisko>Krzanowski</nazwisko> <imie>Andrzej</imie> </autor> <autor> <nazwisko>Krzanowska</nazwisko> <imie>Grażyna</imie> </autor> <rok>1983</rok> <wydawca>PWM</wydawca> <nagranie>KM</nagranie> </kompozycja> ... </lista.kompozycji>
a ma wyglądać tak:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE lista.kompozycji SYSTEM "lkompc.dtd" > <lista.kompozycji> <kompozytor id='Augustyn.R'><!-- *** Augustyn:Rafał# --> <kompozycja typ="i.orkiestro"> <tytul>Atlantyda I na orkiestrę symfoniczną</tytul> <xsklad>4 akordeony w orkiestrze</xsklad> <rok>1979</rok> <sklad>4 acc</sklad> <wydawca>manus</wydawca> </kompozycja> <kompozycja typ="i.orkiestro"> <tytul>Atlantyda II na wielką orkiestrę i chór</tytul> <xsklad>4 akordeony w orkiestrze</xsklad> <rok>1983</rok> <sklad>4 acc</sklad> <wydawca>manus</wydawca> <nagranie>LP</nagranie> </kompozycja> </kompozytor> ... <kompozytor id='Krzanowski.A#Krzanowska.G'><!-- *** Krzanowski:Andrzej#Krzanowska:Grażyna# --> <kompozycja typ="solo"> <tytul>Rapsodia</tytul> <xsklad>akordeon solo</xsklad> <rok>1983</rok> <wydawca>PWM</wydawca> <nagranie>KM</nagranie> </kompozycja> ... </lista.kompozycji>
To znaczy, że
z elementu kompozycja
mają zniknąć elementy autor
.
Wszystkie kompozycje tego samego kompozytora mają być elementami-dziećmi
elementu kompozytor
.
Element kompozytor
ma identyfikować
kompozytora za pomocą atrybutu id
, którego wartość jest wyznaczana
(w przypadku gdy dzieło jest ma jednego autora) jako:
nazwisko.inicjał
W przypadku gdy kompozycja jest dziełem zbiorowym, identyfikator kompozytora zbiorowego ma mieć postać:
nazwisko.inicjał#nazwisko.inicjał nazwisko.inicjał#nazwisko.inicjał#nazwisko.inicjał ...
Powyższe realizuje taki oto skrypt:
#!/usr/bin/perl use XML::DOM; binmode(STDOUT, ":utf8"); my $file2parse = $ARGV[0]; my $parser = new XML::DOM::Parser; my $doc = $parser->parsefile ($file2parse); for my $kompozycja ( $doc->getElementsByTagName ("kompozycja") ) { my $author_id = ''; ## przeglądamy kolejne elementy autor: for my $autor ($kompozycja->getElementsByTagName("autor")) { $im = ($autor->getElementsByTagName("imie"))[0]->toString(); $nz = ($autor->getElementsByTagName("nazwisko"))[0]->toString(); $author_id .= "$nz:$im#"; ## autorów może być dużo stąd .= a nie = $author_id =~ s/<[^<>]+>//g; ## usuń tagi, zostaw sam tekst ##print STDERR "$author_id\n"; ## usuń element autor: $kompozycja->removeChild($autor); } ## Hash of Arrays, cf http://docstore.mik.ua/orelly/perl2/prog/ch09_02.htm push @{ $Kompozycje{ $author_id }}, $kompozycja->toString (); } ### Druk ############################################################ print "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; print "<!DOCTYPE lista.kompozycji SYSTEM \"lkompc.dtd\" >\n"; print "<lista.kompozycji>\n"; for $autor (sort keys %Kompozycje ) { $autor_i = $autor; $autor_i =~ s/:([^#:])[^#:]+#/.\1#/g; # tylko inicjały chop($autor_i); print "\n\n\n\n<kompozytor id='$autor_i'><!-- *** $autor -->\n\n"; for $kompozycja ( @{ $Kompozycje{ "$autor" }} ) { print $kompozycja, "\n"; } print "\n</kompozytor>\n"; } print "</lista.kompozycji>\n"; ## koniec ###
Jeżeli się nie doda binmode
, to UTF jest malformed (Ah ten Perl.)
Podpowiedź znalazłem
tutaj.
Nawiasem mówiąc i w innym skrypcie:
s/<imie>([^<>])([^<>]+)<\/imie>/<inicjal>\1<\/inicjal>/gm;
Też zwraca malformed UTF-8 jeżeli np. imieniem jest Łukasz. A jak zaczyna się od A-Z to jest OK.