Search code examples
xmlperlxml-libxml

Adding a new node using XML:libXML throwing error


Here is what the xml looks like

<RasdItemsList xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:rasd="...">
      <Link rel="edit" type="application/vnd.vmware.vcloud.rasdItemsList+xml" href="..."/>
      <Item>
          <rasd:AddressOnParent>0</rasd:AddressOnParent>
          <rasd:Description>Hard disk</rasd:Description>
          <rasd:ElementName>Hard disk 1</rasd:ElementName>
          <rasd:HostResource xmlns:ns12="http://www.vmware.com/vcloud/v1.5" ns12:capacity="59392" ns12:busSubType="lsilogic" ns12:busType="6"></rasd:HostResource>
          <rasd:InstanceID>2000</rasd:InstanceID>
          <rasd:Parent>2</rasd:Parent>
          <rasd:ResourceType>17</rasd:ResourceType>
      </Item>
      <Item>
          <rasd:AddressOnParent>1</rasd:AddressOnParent>
          <rasd:Description>Hard disk</rasd:Description>
          <rasd:ElementName>Hard disk 2</rasd:ElementName>
          <rasd:HostResource xmlns:ns12="http://www.vmware.com/vcloud/v1.5" ns12:capacity="4" ns12:busSubType="lsilogic" ns12:busType="6"></rasd:HostResource>
          <rasd:InstanceID>2001</rasd:InstanceID>
          <rasd:Parent>2</rasd:Parent>
          <rasd:ResourceType>17</rasd:ResourceType>
      </Item>
.. Some more items
</RasdItemsList>

I am trying to add a new Item node to this, i.e a new hard disk using XML::libXML. Here is my code

  my $doc    = $parser->parse_string ($data_xml); 
  my $xpc = XML::LibXML::XPathContext->new($doc);
  $xpc->registerNs('x', 'http://www.vmware.com/vcloud/v1.5');
  $xpc->registerNs('rasd', 'http:...');
  $xpc->registerNs('ns2','http://www.vmware.com/vcloud/v1.5');

  # add a new node
  my $new_item = $doc->createElement("Item");
  my $new_address_on_parent = $doc-> createElement("rasd:AddressOnParent");
  my $new_element_name = $doc->createElement("rasd:ElementName"); 
  my $new_description = $doc->createElement("rasd:Description");
  my $new_InstanceID  = $doc->createElement("rasd:InstanceID");
  my $new_parent = $doc->createElement("rasd:Parent");
  my $new_resource_type = $doc->createElement("rasd:ResourceType");
  my $new_host_resource = $doc->createElement("rasd:HostResource");
  if( my ($node) =  $xpc->findnodes('/x:RasdItemsList/x:Item') )
  {
    my $new_parent =  $node->parentNode;
    $new_parent->appendChild($new_item);
    $new_item->appendChild($new_address_on_parent);
    $new_item->appendChild($new_description);
    $new_item->appendChild($new_element_name);
    $new_item->appendChild($new_host_resource);
    $new_item->appendChild($new_InstanceID);
    $new_item->appendChild($new_parent);
    $new_item->appendChild($new_resource_type);
    $new_address_on_parent->appendText('4');
    $new_description->appendText('Hard disk');
    $new_element_name->appendText('Hard Disk 4');
    $new_host_resource->appendText("What to add");
    $new_InstanceID->appendText('2004');
    $new_parent->appendText('2');
    $new_resource_type->appendText('17');

This is throwing error saying "appendChild: HIERARCHY_REQUEST_ERR". I tried to add child one by one and it works until I add Elementname. After that whatever I try to add I get the above error.

Also I am not sure how to add rasd:HostResource child text.

Thanks in advance for the help.


Solution

  • $new_parent is the culprit. It is used as the parent of the item node already, so can not be used again to be added as a child node of item. The following line is creating the problem. $new_item->appendChild($new_parent);

    I fixed these two lines and it worked.

     my $new_parent =  $node->parentNode;
     $new_parent->appendChild($new_item);
    
    to 
    my $new_parent_node = $node->parentNode;
    $new_parent_node->appendChild($new_item);