ysth
ysth

Reputation: 98398

How to create nodes to append when using XML::LibXML to write XML?

I am creating an XML document and adding a complicated node to it in a loop, similar to the following example.

The following works, but feels kludgy in how it creates $row_template. Is there not some more specific way to create a document fragment to reuse from an xml string?

use 5.022;
use warnings;
use XML::LibXML;

my $xml = '<?xml version="1.0"?><RootNode><Outer1><Outer2/></Outer1></RootNode>';
my $row_parent_xpath = '//Outer2';
my $row_xml = '<DetailNode><Field1/><Field2/></DetailNode>';

# create the document
my $doc = XML::LibXML->load_xml('string' => $xml);
# find where we will be inserting nodes
my ($parent) = $doc->findnodes($row_parent_xpath);

# create a template for the nodes to insert
my $row_template = XML::LibXML->load_xml('string' => $row_xml)->documentElement;
$row_template->setOwnerDocument($doc);

for my $row_data ({field1=>'Foo',field2=>'Bar'}, {field1=>'Baz',field2=>'Quux'}) {
    my $row = $row_template->cloneNode(1);
    $parent->appendChild($row);
    $_->appendChild($doc->createTextNode($row_data->{field1})) for $row->findnodes('Field1');
    $_->appendChild($doc->createTextNode($row_data->{field2})) for $row->findnodes('Field2');
}

say $doc->toString(1);

output:

<?xml version="1.0"?>
<RootNode>
  <Outer1>
    <Outer2>
      <DetailNode>
        <Field1>Foo</Field1>
        <Field2>Bar</Field2>
      </DetailNode>
      <DetailNode>
        <Field1>Baz</Field1>
        <Field2>Quux</Field2>
      </DetailNode>
    </Outer2>
  </Outer1>
</RootNode>

Upvotes: 3

Views: 855

Answers (1)

nwellnhof
nwellnhof

Reputation: 33658

libxml2 has xmlParseBalancedChunkMemory which also takes a document. XML::LibXML has parse_balanced_chunk but this doesn't allow to set the document. I'm not sure whether you have to call setOwnerDocument. When appending the cloned node, the owner document should be set automatically.

Upvotes: 2

Related Questions