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


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


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

  • 3
    This is no valid XML. An XML file has one root tag.
    – Cyrus
    Commented Oct 25, 2014 at 14:53

3 Answers 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:

 <mm />
 <nn />

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' );

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;

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


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

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

xml-cut from xml-coreutils may accomplish your needs

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .