Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

XML::Simple how do i keep the same xml format (Values and Attributs)?

by tobias_hofer (Friar)
on Jun 14, 2013 at 10:04 UTC ( [id://1038934]=perlquestion: print w/replies, xml ) Need Help??

tobias_hofer has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks.

I am using XML::Simple for xml processing.
I read in following from a file:
<TABLE> <TABLE-CAPTION ID="ID64706055682598"> <LONG-NAME>TABLE NAME</LONG-NAME> </TABLE-CAPTION> <TGROUP COLS="4"> <COLSPEC COLNUM="1" COLNAME="col1" COLWIDTH="1.00*"/> <COLSPEC COLNUM="2" COLNAME="col2" COLWIDTH="1.00*"/> <COLSPEC COLNUM="3" COLNAME="col3" COLWIDTH="1.00*"/> <COLSPEC COLNUM="4" COLNAME="col4" COLWIDTH="1.00*"/> <TBODY> <ROW> <ENTRY COLNAME="col1">A</ENTRY> <ENTRY COLNAME="col2">B</ENTRY> <ENTRY COLNAME="col3">C</ENTRY> <ENTRY COLNAME="col4">D</ENTRY> </ROW> <ROW> <ENTRY COLNAME="col1">E</ENTRY> <ENTRY COLNAME="col2">F</ENTRY> <ENTRY COLNAME="col3">G</ENTRY> <ENTRY COLNAME="col4">H</ENTRY> </ROW> </TBODY> </TGROUP> </TABLE>
And I want to write the same to file. Thing is, that when i am putting the xml to file some values become xml-attributes.
So in the end i got this:
<TABLE> <TABLE-CAPTION ID="ID64706055682598" LONG-NAME="TABLE NAME" /> <TGROUP COLS="4"> <COLSPEC COLNAME="col1" COLNUM="1" COLWIDTH="1.00*" /> <COLSPEC COLNAME="col2" COLNUM="2" COLWIDTH="1.00*" /> <COLSPEC COLNAME="col3" COLNUM="3" COLWIDTH="1.00*" /> <COLSPEC COLNAME="col4" COLNUM="4" COLWIDTH="1.00*" /> <TBODY> <ROW> <ENTRY COLNAME="col1">A</ENTRY> <ENTRY COLNAME="col2">B</ENTRY> <ENTRY COLNAME="col3">C</ENTRY> <ENTRY COLNAME="col4">D</ENTRY> </ROW> <ROW> <ENTRY COLNAME="col1">E</ENTRY> <ENTRY COLNAME="col2">F</ENTRY> <ENTRY COLNAME="col3">G</ENTRY> <ENTRY COLNAME="col4">H</ENTRY> </ROW> </TBODY> </TGROUP> </TABLE>
This read about parameters to XML Simple like VauleAttr and KeyAttr but it seems to have no effect. As far as i have understood i can define with ValueAttr what should be printed as Value and not as Attribute.. Maybe i have misunderstood this API? The same idea i have form KeyAttr so i can define what hash-keys are in the end Attributes and no values..

I am stuck in the middle, any help is highly welcome!
Here my prototype where i read in the an xml-file with the content of the first XML-structure i have put here. By this i can check if (at the end) i will get the same XML-structure back when looking at $xml:

use XML::Simple; use strict; my $xmlParser = new XML::Simple( RootName => 'TABLE', KeepRoot=>1, ValueAttr=>{ 'TABLE-CAPTION' => 'LONG-NAME', }); my $data = $xmlParser->XMLin("testtable.xml"); my $xml = $xmlParser->XMLout($data); print "stop";

Any help is highly welcome!

Regards!
Tobias

Replies are listed 'Best First'.
Re: XML::Simple how do i keep the same xml format (Values and Attributs)?
by hdb (Monsignor) on Jun 14, 2013 at 11:01 UTC

    There is also NoAttr => 1 in XML::Simple but that goes into the other extreme.

      I had occasion to use both the OP's solution and NoAttr => 1 on a project where rewriting existing XML::Simple to use a different module wasn't an option.

      When writing new modules for the project, I used XML::Twig or XML::LibXML. Didn't know about XML::Rules; I'll have to check it out.

Re: XML::Simple how do i keep the same xml format (Values and Attributs)? (XML::Rules)
by Anonymous Monk on Jun 14, 2013 at 10:08 UTC
Re: XML::Simple how do i keep the same xml format (Values and Attributs)?
by tobias_hofer (Friar) on Jun 14, 2013 at 10:45 UTC
    I cannot switch to XML::Rules.. i need to get this done by XML::Simple..
    I wonder why this attribute and value stuff is working in all xml-tags but this 'LONG-NAME' tag..
    ???

      Then you are stuck between a rock and a hard place. You don't want to switch away from XML::Simple, yet the author of XML::Simple freely admits that it's not suitable for the sort of task you're describing and recommends other modules instead. Quotes from the documentation:

      "XML::Simple is able to present a simple API because it makes some assumptions on your behalf. These include:

      • [...]
      • "You don't want fine-grained control of the formatting of generated XML
      • [...]

      "In a serious XML project, you'll probably outgrow these assumptions fairly quickly.

      [...]

      "For event based parsing, use SAX (do not set out to write any new code for XML::Parser's handler API - it is obselete).

      "For tree-based parsing, you could choose between the 'Perlish' approach of XML::Twig and more standards based DOM implementations - preferably one with XPath support such as XML::LibXML."

      Personally I use XML::LibXML for virtually any XML-handling task that's thrown my way, and am rarely disappointed by it.

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
        Yes, you are right..
        If I am lucky I can convince people installing this package so I can switch to it. Thanks a lot!

        However, I have found a solution :-))

        XML Simple puts nearly every hash as an XML-attribute. But not if its pointing to another hash, example
        :
        $tdata->{'TABLE-CAPTION'} = {'ID' => $_id, 'LONG-NAME' => {content => +'Test results'}};
        Using content will create another XML-tag and not an attribute. But for using this I had to configure XML-Simple like this.
        my $xmlParser = new XML::Simple( RootName => 'TABLE', KeepRoot=>1, ValueAttr=>{ 'TABLE-CAPTION' => 'ID', 'ContentKey' => 'content', }
        Now its working fine, look at this: ^^
        P>Testresults:</P><TABLE> <TABLE-CAPTION ID="ID42.401123046875"> <LONG-NAME>Testresults</LONG-NAME> </TABLE-CAPTION> <TGROUP COLS="4"> <COLSPEC COLNAME="test-id" COLNUM="0" COLWIDTH="1.00*" /> <COLSPEC COLNAME="status" COLNUM="1" COLWIDTH="1.00*" /> <COLSPEC COLNAME="test-spec" COLNUM="2" COLWIDTH="1.00*" /> <COLSPEC COLNAME="requirement-ids" COLNUM="3" COLWIDTH="1.00*" /> <TBODY> <ROW> <ENTRY COLNAME="test-id"> ...

        Thank you very much for all your hints and tips!

        Best regards!!
        Tobias

      XML::Rules is a single .pm file and its only non-core dependency is XML::Parser which you most probably already have so if you can create/upload your script, you can "install"/upload XML::Rules. No compilation or configuration required, you just need to put the Rules.pm into a directory named XML in one of the directories listed by perl -e "print join qq{\n}, @INC".

      Yes, even you can use CPAN

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

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (5)
As of 2024-04-18 13:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found