SPUG: Generating XML -- XML::Generator, XML::XPath, nsgmls, etc.

Adam Monsen meonkeys at hotmail.com
Tue Nov 20 22:46:48 CST 2001


Here's a quick demo of XML::Generator, one I haven't seen mentioned yet. 
I've found XML::Writer runs faster, but I like the syntax of XML::Generator.

--BEGIN xml_gen_test.pl----------------------------
#!/usr/bin/perl -w
use XML::Generator;
use strict;

my $xml = XML::Generator->new(escape => 'always',
                              pretty => 2,
                              conformance => 'strict');

print $xml->DataTribe(
        $xml->SendFunc(
          $xml->AcknowledgeAddrs(
            $xml->EmailAddress('amonsen at example.com'),
            $xml->EmailAddress('meonkeys at hotmail.com'),
          ),
          $xml->ClientName('MarketSuckemdry & Buy, INC.'),
          $xml->ImportData(
            $xml->Row(
              $xml->UserID('0157H7'),
              $xml->Column({ Name => 'Car'}, 'Honda'),
              $xml->Column({ Name => 'Sex'}, 'Female'),
            ),
          ),
        ),
);
--END   xml_gen_test.pl----------------------------

Close all your parens properly and you're guaranteed well-formed XML! This 
is basically a compile-time check for well-formedness. It also has easy ways 
to handle namespaces, CDATA, comments, <!DOCTYPE... declarations, etc.

Here's the output of the above xml_gen_test.pl:
--START xml output---------------------------------
<DataTribe>
  <SendFunc>
    <AcknowledgeAddrs>
      <EmailAddress>amonsen at example.com</EmailAddress>
      <EmailAddress>meonkeys at hotmail.com</EmailAddress>
    </AcknowledgeAddrs>
    <ClientName>MarketSuckemdry &amp; Buy, INC.</ClientName>
    <ImportData>
      <Row>
        <UserID>0157H7</UserID>
        <Column Name="Car">Honda</Column>
        <Column Name="Sex">Female</Column>
      </Row>
    </ImportData>
  </SendFunc>
</DataTribe>
--END   xml_output---------------------------------

For checking XML validity against a DTD, I use nsgmls. I don't know an easy 
way to validate XML with Perl.

For Retrieving data, XML::XPath is a great way to get at a specific piece of 
data. I ran this script on xml_output above...
--BEGIN XML-XPath_test.pl--------------------------
#!/usr/bin/perl -w

use XML::XPath;
use XML::XPath::XMLParser;
use strict;

my $xml;
while (<>) { $xml .= $_; }

my $parser = XML::XPath::XMLParser->new(xml => $xml);
my $root_node = $parser->parse;
my $xpath = XML::XPath->new(context => $root_node);
my $clientname = $xpath->find('/DataTribe/SendFunc/ClientName/text()');
print "Client is $clientname for this transaction\n";
--END   XML-XPath_test.pl--------------------------

And here is the result.
--BEGIN xpath test output--------------------------
Client is MarketSuckemdry & Buy, INC. for this transaction
--END   xpath test output--------------------------

Notice how the amperstand was conveniently un-escaped. Not sure if I made 
any dumb mistakes above, but anyway, Good luck! Please let me (and 
spug-list) know what you find out.
-Adam


>From: Colin Meyer <cmeyer at helvella.org>
>To: spug-list at pm.org
>Subject: SPUG: Generating XML
>Date: Tue, 20 Nov 2001 11:02:15 -0800
>
>SPUGsters,
>
>Amidst 90% the offtopic messages on this list recently, here's a
>question about dealing with XML from Perl.
>
>I've done a fair bit of work with XML in Perl, but typically it has had
>to do with receiving information formatted in XML, with the task of
>having to decipher the contents and sift the groolly bits of data out.
>My current project adds another task: generating XML to match particular
>DTDs. I'll receive Perl data structures, and need to translate them into
>valid XML.
>
>I've two thoughts on how to do this. In my simple proof-of-concept
>program sketches, they seem to be approximately equal. One is to use a
>template file, and fill in the changing pieces, and the other is to
>create a DOM structure, and then call its $d->toString() method. Does
>anyone on the list have experience with either of these styles of
>generating XML? A third style that I haven't tried would be to create
>a system that would interpret the Perl data structure, and then
>generate SAX events. This also seems easy enough, but I haven't played
>with it yet.
>
>A SAX style pipeline for all processing from input to output won't work
>in this case, as the data from the querying doc is quite different than
>the data of the replying doc.
>
>The tricky bit that I haven't solved is complying to the DTD in such
>a manner that I'll be sure that my generated doc is correct.
>
>Thanks for any advice,
>-C.
>
>  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>      POST TO: spug-list at pm.org       PROBLEMS: owner-spug-list at pm.org
>       Subscriptions; Email to majordomo at pm.org:  ACTION  LIST  EMAIL
>   Replace ACTION by subscribe or unsubscribe, EMAIL by your Email-address
>  For daily traffic, use spug-list for LIST ;  for weekly, spug-list-digest
>      Seattle Perl Users Group (SPUG) Home Page: http://zipcon.net/spug/
>
>


_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp


 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     POST TO: spug-list at pm.org       PROBLEMS: owner-spug-list at pm.org
      Subscriptions; Email to majordomo at pm.org:  ACTION  LIST  EMAIL
  Replace ACTION by subscribe or unsubscribe, EMAIL by your Email-address
 For daily traffic, use spug-list for LIST ;  for weekly, spug-list-digest
     Seattle Perl Users Group (SPUG) Home Page: http://zipcon.net/spug/





More information about the spug-list mailing list