gr.d has asked for the wisdom of the Perl Monks concerning the following question:

I'm writing a perl script where I need to separate the XML(datamod) into two XML files.

<Root> <Top> <Module name="ALU"> <input name="po_ctrl"/> <bidirection name="add"/> </Module> <Module name="Po_ctrl"> <input name="ctrl"/> <output name="ctrlbus"/> <bidirection name="add"/> </Module> <input name="add"/> <input name="clk"/> <input name="da_in"/> <output name="da_out"/> <bidirection name="ctrl"/> </Root> </Top>
Posting the perl snippet here for reference purposes
open(IN_FILE, "<datamod.xml") or die "Cant open input file"; open(TM1_FILE, ">tm1.xml") or die "Cant Open tm1.xml"; open(TM2_FILE, ">tm2.xml") or die "Cant Open tm2.xml"; my $chk = 0; while(my $line = <IN_FILE>){ $line =~ s/^\s+//; @xwords = split(" ",$line); if($xwords[0] ne "<Module" and $xwords[0] ne "</Module>" and $chk == +0) { print TM1_FILE $line; } else { print TM2_FILE $line; $chk = 1; } if($xwords[0] eq "</Module>" and $chk == 1) { $chk = 0; } } close TM1_FILE; close TM2_FILE;

Expected files

Temp file 1:

<Root> <Top> <input name="add"/> <input name="clk"/> <input name="da_in"/> <output name="da_out"/> <bidirection name="ctrl"/> </Top> </Root>

Temp File 2

<Root> <Top> <Module name="ALU"> <input name="po_ctrl"/> <bidirection name="add"/> </Module> <Module name="Po_ctrl"> <input name="ctrl"/> <output name="ctrlbus"/> <bidirection name="add"/> </Module> </Root> </Top>

NOTE: I'm using the XML::Simple module because the Perl script is written in it and it's tedious to convert to any other XML module.

Any help is appreciated, kindly post the rewritten snippet!

Replies are listed 'Best First'.
Re: Separate a single xml into mulitple XML using perl
by GrandFather (Saint) on Jan 06, 2016 at 07:11 UTC

    XML::Simple is designed for simple XML documents. It is not designed to be a simple to use XML parser. Trying to do "interesting" stuff with XML::Simple is a recipe for misery. In the long run (say in an hour) converting to something like XML::Twig will be less tedious and make your life much happier than persisting in trying to hammer XML::Simple into shape for a job it wasn't designed for.

    Seriously, have a serious crack at using XML::Twig. If you haven't made solid progress in an hour come back for some tips.

    Premature optimization is the root of all job security

      I do find XML::Twig pretty easier, My superiors are so adamant on sticking to XML::Simple, I don't get a say in that. That's the reason as of now I'm sticking with XML::Simple. But can anything be done on the code I posted? Really appreciate the help

        My superiors are so adamant on sticking to XML::Simple
        Perhaps you should try to have them read this: XML::Simple needs to go!

        See Simpler than XML::Simple

        If you have XML::Simple, you most likely also have XML::Parser & XML::Parser::Expat. XML::Rules is a plain Perl module on top of XML::Parser::Expat, so you don't really need to build and install it into the Perl directories, you can use it as a module you write yourself and copy it with the rest of your app/scripts.

        I believe you can do the same with XML::Twig.

        Jenda
        Enoch was right!
        Enjoy the last years of Rome.

        But can anything be done on the code I posted?

        Yes, it can be ignored :)

        It doesn't use XML::Simple, its parsing xml by hand

        The xml file you posted isn't valid

Re: Separate a single xml into mulitple XML using perl
by Jenda (Abbot) on Jan 06, 2016 at 15:39 UTC

    If I understand you right you want all <Module> tags into one file and all other tags directly in <Root><Top> into the other, right? This is what it could look like using XML::Rules:

    use strict; use XML::Rules; open MODULE, '>', 'splitXML-test-Module.xml'; print MODULE "<Root>\n <Top>\n"; open OTHER, '>', 'splitXML-test-Other.xml'; print OTHER "<Root>\n <Top>\n"; my $parser = XML::Rules->new(rules => { Root => '', Top => '', Module => [ '/Root/Top' => sub { my ($tag_name, $attrs, $context, $parent_data, $parser) = +@_; print MODULE ' ' . $parser->ToXML($tag_name, $attrs) . "\ +n"; return; }, 'raw' ], _default => [ '/Root/Top' => sub { my ($tag_name, $attrs, $context, $parent_data, $parser) = +@_; print OTHER ' ' . $parser->ToXML($tag_name, $attrs) . "\n +"; return; }, 'raw' ] }); $parser->parse(\*DATA); print MODULE " </Top>\n</Root>\n"; print OTHER " </Top>\n</Root>\n"; __DATA__ <Root> <Top> <Module name="ALU"> <input name="po_ctrl"/> <bidirection name="add"/> </Module> <Module name="Po_ctrl"> <input name="ctrl"/> <output name="ctrlbus"/> <bidirection name="add"/> </Module> <input name="add"/> <input name="clk"/> <input name="da_in"/> <output name="da_out"/> <bidirection name="ctrl"/> </Top> </Root>

    Basically you specify that you do not want to "return" anything from the <Root> and <Top> nodes, that the <Module> tags directly under <Root><Top> should be printed (including attributes and content) into the MODULE filehandle and otherwise just remembered for the parent tag. That other tags if directly under <Root><Top> should be printed to the OTHER filehandle and otherwise remembered.

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Re: Separate a single xml into mulitple XML using perl
by Anonymous Monk on Jan 06, 2016 at 08:20 UTC

    /me whistles

    $ xml_split -v -i -c Module junk1152042.xml

    generating main file junk1152042-00.xml generating junk1152042-01.xml generating junk1152042-02.xml $ cat junk1152042-00.xml <Root> <Top> <xi:include href="junk1152042-01.xml"/> <xi:include href="junk1152042-02.xml"/> <input name="add"/> <input name="clk"/> <input name="da_in"/> <output name="da_out"/> <bidirection name="ctrl"/> </Top> </Root> $ cat junk1152042-01.xml <Module name="ALU"> <input name="po_ctrl"/> <bidirection name="add"/> </Module> $ cat junk1152042-02.xml <Module name="Po_ctrl"> <input name="ctrl"/> <output name="ctrlbus"/> <bidirection name="add"/> </Module> $
Re: Separate a single xml into mulitple XML using perl
by gr.d (Novice) on Jan 07, 2016 at 09:00 UTC

    Thank you everyone!!