2

I have an xml file that have different nodes, I want to split files like this:

<unix>
 <mm>
</unix>
<osx>
 <nn>
</osx>

When I run the script I want it to make one xml file called unix.xml, which contains this

<unix
 <mm>
</unix>

And then another xml file called osx.xml, which contains this

<osx>
 <nn>
</osx>
1
  • 3
    This is no valid XML. An XML file has one root tag.
    – Cyrus
    Oct 25, 2014 at 14:53

3 Answers 3

3

First off - I'll say I think it's quite a bad idea to do XML parsing with anything other than an XML parser. Regular expressions may look like they're going to work, but this is a really good way to make some brittle code - XML that's semantically equivalent can look different to different REs (such as indents/linefeeds and unary tags).

So with that in mind - I would use Perl and the XML::Twig library. This is a pretty standard thing - there are prebuilt packages ubiquitously available.

However perhaps most importantly of all - the XML you have posted is NOT valid. I'm going to assume that's because it's a sample, and not the real XML, and so you've missed a bit off. I'm using as my sample:

<root>
<unix>
 <mm />
</unix>
<osx>
 <nn />
</osx>
</root>

And using this code will do what you ask for:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new( 'pretty_print' => 'indented' );
$twig->parsefile("your_xml.xml");

foreach my $element ( $twig->root->children ) {
    my $tag = $element->tag;
    print "Processing $tag\n";

    #print to STDOUT for debugging
    print $element ->sprint;

    #print to output file
    open( my $output, ">", "$tag.xml" ) or warn $!;
    print {$output} $element->sprint;
    close($output);
}

If of course, your posting of XML is literally what you have, then it is broken XML and you should ideally go and hit whoever gave you it a with a rolled up copy of the spec document. If that is impractical due to it being real life, then I would offer you this answer on Stack Overflow: https://stackoverflow.com/a/28913945/2566198

0

I think the follow should help. This is usual task which should to do between two limits.

unset f t
while read l
do
  t=${t:+$t\\n}$l
  l=${l//[<>]/}
  : ${f:="$l"}
  if [ "$l" = "/$f" ]
  then
    echo -e "$t" > "$f".xml 
    unset f t
  fi
done < <(cat your_xml_file)
0

xml-cut from xml-coreutils may accomplish your needs

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.