Beefy Boxes and Bandwidth Generously Provided by pair Networks Cowboy Neal with Hat
Perl-Sensitive Sunglasses
 
PerlMonks  

Problem to add xml element in a formatted structure

by gdanenb (Acolyte)
on Feb 09, 2012 at 09:07 UTC ( #952674=perlquestion: print w/ replies, xml ) Need Help??
gdanenb has asked for the wisdom of the Perl Monks concerning the following question:

For some reason when I append element to xml file, it's written in one line, i.e. not formatted

Original xml:

<configuration> <property> <name>test1</name> </property> </configuration>
And the code is:
my $parser =XML::LibXML->new(); my $doc =$parser->parse_file($file) or die $!; my $root =$doc->getDocumentElement; my $searchPath="/configuration"; my ($val)=$root->findnodes($searchPath); my $propTag=$doc->createElement("property"); $val->appendChild($propTag); my $nameTag=$doc->createElement("name"); $nameTag->appendTextNode($name); $propTag->appendChild($nameTag); $doc->setDocumentElement($root); $doc->toFile($file,1);
Which resulted with:
<configuration> <property> <name>test1</name> </property> <property><name>test2</name></property></configuration>
instead of:
<configuration> <property> <name>test1</name> </property> <property> <name>test2</name> </property> </configuration>

Comment on Problem to add xml element in a formatted structure
Select or Download Code
Re: Problem to add xml element in a formatted structure
by tobyink (Abbot) on Feb 09, 2012 at 11:06 UTC

    In general, whitespace in XML is considered significant. OK, in many dialects of XML nobody cares about whitespace, but because it does matter in some XML dialects, general XML tools (such as XML::LibXML) will not insert whitespace for you.

    Firstly, you should ask yourself, do you care about indenting and pretty formatting the XML? I agree that it's nice to have, but do you want it at the cost of potentially complicating and slowing down your code?

    In some cases the answer to this is no. If the XML is only ever going to be processed by scripts, then it doesn't matter what it looks like, as long as it works.

    In other cases, you know that the XML you're generating is likely to be read and edited by humans with text editors. So slowing your code down and complicating it might be worth the pay-off.

    If you decide that you don't care about whitespace, then you're done. Your code is working fine.

    If you do care about whitespace, you've got two alternative solutions:

    • Include a bunch of $tag->appendTextNode("\n     "); sort of things sprinkled in your code to ensure that all the linebreaks and whitespace you want get generated. Or;
    • Generate your XML as you are doing it now, and then post-process it using an existing XML formatting tool.

    The first option will keep your code running roughly at the current speed, but litters your code with junk that is likely to make it less maintainable.

    The second option is likely to slow down your script somewhat (though with small files like the one you give as an example, negligibly) but doesn't clutter your code as much.

    One module that can prettify your XML is XML::LibXML::PrettyPrint. There are others, but I personally think it's the best of the bunch. (Though I did write it, so I would!) Here's how you'd change your code to use it... Replace this:

    $doc->toFile($file,1);

    With this:

    require XML::LibXML::PrettyPrint; XML::LibXML::PrettyPrint -> new( element => {inline=>['name']} ) -> pretty_print($doc) -> toFile($file);

    Setting name as an inline element ensures that your output is formatted like this:

    <configuration> <property> <name>test1</name> </property> <property> <name>test2</name> </property> </configuration>

    The default (without making any elements inline) would have been like this:

    <configuration> <property> <name> test1 </name> </property> <property> <name> test2 </name> </property> </configuration>

    Using the defaults allows you to simplify your code even more though:

    require XML::LibXML::PrettyPrint; XML::LibXML::PrettyPrint->pretty_print($doc)->toFile($file);

      In my case human readable format is important
      Additional module is problematic as well. since this is on running site

      I don't understand why creating a new document with
      $doc->toString(1) or $doc-toFile($f,1)
      is working fine
      Only when appending elements the problem appear... I used xmllint --format to format xml structure but it's not pure perl way...

        So you are able to modify the code on a running site, but not add a module to implement your need on a running site? What if you were to modify your code by cutting and pasting the code from the module?

        Just trying to understand where that line is drawn, and possibly getting you to evaluate why.

        --MidLifeXis

Re: Problem to add xml element in a formatted structure
by choroba (Abbot) on Feb 09, 2012 at 12:49 UTC
    Crossposted at StackOverflow. It is considered polite to inform about crossposting so people do not waste their time on finding solutions someone else has already found in the other site.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://952674]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (11)
As of 2014-04-18 09:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (465 votes), past polls