How to append XML string into a DOMDocument object? - php

Creating the DOMDocument object:
$getToken = '<getToken>...</getToken>';
$getToken_objeto = new DOMDocument("1.0", "UTF-8");
$getToken_objeto -> loadXML($getToken);
Trying to append a XML string (Signature) into the DOMDocument created above:
$Signature = '<Signature>...</Signature>';
$Signature_objeto = new DOMDocument("1.0", "UTF-8");
$Signature_objeto -> loadXML($Signature);
$Signature_nodeList = $Signature_objeto -> getElementsByTagName("Signature");
$Signature_node = $Signature_nodeList -> item(0);
$getToken_objeto -> importNode($Signature_node, true);
$getToken_objeto -> appendChild($Signature_node);
I get 2 errors:
Fatal error: Uncaught exception 'DOMException' with message 'Wrong Document Error' in C:...
DOMException: Wrong Document Error in C:...
Seems simple to resolve but im quite unexperienced using the PHP DOM extension.
Thanks in advance.

You're trying to append the original node - not the imported one.
$Signature_node = $getToken_objeto->importNode(
$Signature_nodeList->item(0), true
);
You're trying to append the node to the document, but an XML document can only have a single document element and it already has one. You can append it to the document element:
$getToken_objeto->documentElement->appendChild($Signature_node);
But PHP can load XML fragments directly into a DOMDocumentFragment.
$xml = '<getToken>...</getToken>';
$fragmentXml = '<Signature>...</Signature>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXpath($dom);
$fragment = $dom->createDocumentFragment();
$fragment->appendXml($fragmentXml);
$xpath
->evaluate('//getToken')
->item(0)
->appendChild($fragment);
echo $dom->saveXml();

Related

print_r for nodeList is not working

I have the following source code:
<?php
function getTerms()
{
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML('https://charitablebookings.com/terms'); // loads your HTML
$xpath = new DOMXPath($doc);
// returns a list of all links with rel=nofollow
$nodeList = $xpath->query("//div[#class='terms-conditions']");
$temp_dom = new DOMDocument();
$node = $nodeList->item(0);
$temp_dom = new DOMDocument();
foreach($nodeList as $n) $temp_dom->appendChild($temp_dom->importNode($n,true));
print_r($temp_dom->saveHTML());
}
getTerms();
?>
which I'm trying to get a text from a web page by getting a specific class. I don't get anything on my browser when I try to print_r the temp_dom. And $node is null. What am I doing wrong ?
Thanks for your time
The first issue is that DOMDocument's loadHTML method expects HTML content as its first parameter, not an URL.
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$html = file_get_contents('https://charitablebookings.com/terms');
$doc->loadHTML($html);
And the second problem is with your XPath expression: $xpath->query("//div[#class='terms-conditions']") - as there is no div with class of terms-conditions in the document (it probably gets added by some JavaScript loader).

Search within XML with PHP code

this is my code and i am trying to show the value of xml using Xpath but when i run this i am getting error in my code.
Here is the code
<?php
$load = new DOMDocument();
$load = simplexml_load_file("testing.xml");
var_dump($load);
$xpath = new DOMXpath($load);
var_dump($xpath);
$path1 = "/clip/metadata[name=keywords]/value";
$query = $xpath->query($path1);
var_dump("$query");
?>
this is the error, which i am getting
Catchable fatal error: Argument 1 passed to DOMXPath::__construct() must be an instance of DOMDocument, instance of SimpleXMLElement given in C:\xampp\htdocs\xml-text\index.php on line 5
As the error states, you are not passing the constructor the appropriate arguments. simplexml_load_file returns a SimpleXmlElement object, NOT a DOMDocument object.
As stated in the error, you are passing a SimpleXmlElement object instead of a DOMDocument object.
My previous answer was incorrect. It showed how to convert a SimpleXmlElement to a DOMElement not a DOMDocument.
http://php.net/manual/en/domdocument.load.php is how to properly load an xml file into a DOMDocument object.
$load = new DOMDocument();
$load->load("testing.xml");
$xpath = new DOMXpath($load);
Specifically to get the value of the node with the name Keywords you would do something like this
$load = new DOMDocument();
$load->preserveWhiteSpace = false;
$load->load(__DIR__ . "/testing.xml");
$xpath = new DOMXpath($load);
$path1 = '//clip/metadata/name[ . = "Keywords"]';
$query = $xpath->query($path1);
foreach($query as $entry) {
$value = $entry->parentNode->childNodes->item(1)->nodeValue;
}

PHP DOMDocument - createDocumentFragment does not work with loadHTML

I have a string that contains HTML and I would like to insert this HTML in a DOMElement.
For that, I did:
$abstract = "<p xmlns:default="http://www.w3.org/1998/Math/MathML">Test string <formula type="inline"><default:math xmlns="http://www.w3.org/1998/Math/MathML"><default:mi>π</default:mi></default:math></formula></p>"
$dom = new \DOMDocument();
#$dom->loadHTML($abstract);
$frag = $dom->createDocumentFragment();
When var dumping the $frag->nodeValue, I am getting null. Any idea?
I am not sure what you expect, you creating a new fragment and you add no content. Even if you do it would not work because the document fragment is no node, it is an helper construct to add a XML fragment to a document.
Here is an example:
$dom = new \DOMDocument();
$body = $dom->appendChild($dom->createElement('body'));
$fragment = $dom->createDocumentFragment();
$fragment->appendXml('<p>first</p>second');
$body->appendChild($fragment);
echo $dom->saveHtml();
Output:
<body><p>first</p>second</body>

domDocument extract data

I have a very simple code with domDocumet, but it has a mistake I can't solve:
function getTagXML($mensaje, $tagname){
$dom = new domDocument('1.0', 'UTF-8');
libxml_use_internal_errors(true);
// load the html into the object ***/
$dom->loadHTML($mensaje);
//discard white space
$dom->preserveWhiteSpace = false;
$nodeList= $dom->getElementsByTagName($tagname); // here u use your desired tag
$node = $nodeList->item(0);
$item = trim($node->nodeValue);
libxml_clear_errors();
return $item;
}
I got the error:
Notice: Trying to get property of non-object in line 82:
The line 82:
$item = trim($node->nodeValue);
The error message means that $nodeList isn't an object, which means that $dom->getElementsByTagName($tagname) returned NULL.
Based on your other question I would assume that this happens because your XML document is malformed, that is it's missing a root node.

replace html using DOMDocument in PHP

I'm trying to cleanup some bad html using DOMDocument. The html has an <div class="article"> element, with <br/><br/> instead of </p><p> -- I want to regex these into paragraphs...but can't seem to get my node back into the original document:
//load entire doc
$doc = new DOMDocument();
$doc->loadHTML($htm);
$xpath = new DOMXpath($doc);
//get the article
$article = $xpath->query("//div[#class='article']")->parentNode;
//get as string
$article_htm = $doc->saveXML($article);
//regex the bad markup
$article_htm2 = preg_replace('/<br\/><br\/>/i', '</p><p>', $article_htm);
//create new doc w/ new html string
$doc2 = new DOMDocument();
$doc2->loadHTML($article_htm2);
$xpath2 = new DOMXpath($doc2);
//get the original article node
$article_old = $xpath->query("//div[#class='article']");
//get the new article node
$article_new = $xpath2->query("//div[#class='article']");
//replace original node with new node
$article->replaceChild($article_old, $article_new);
$article_htm_new = $doc->saveXML();
//dump string
var_dump($article_htm_new);
all i get is a 500 internal server error...not sure what I'm doing wrong.
There are several issues:
$xpath->query returns a nodeList, not a node. You must select an item from the nodeList
replaceChild() expects as 1st argument the new node, and as 2nd the node to replace
$article_new is part of another document, you first must import the node into $doc
Fixed code:
//load entire doc
$doc = new DOMDocument();
$doc->loadHTML($htm);
$xpath = new DOMXpath($doc);
//get the article
$article = $xpath->query("//div[#class='article']")->item(0)->parentNode;
//get as string
$article_htm = $doc->saveXML($article);
//regex the bad markup
$article_htm2 = preg_replace('/<br\/><br\/>/i', '</p>xxx<p>', $article_htm);
//create new doc w/ new html string
$doc2 = new DOMDocument();
$doc2->loadHTML($article_htm2);
$xpath2 = new DOMXpath($doc2);
//get the original article node
$article_old = $xpath->query("//div[#class='article']")->item(0);
//get the new article node
$article_new = $xpath2->query("//div[#class='article']")->item(0);
//import the new node into $doc
$article_new=$doc->importNode($article_new,true);
//replace original node with new node
$article->replaceChild($article_new, $article_old);
$article_htm_new = $doc->saveHTML();
//dump string
var_dump($article_htm_new);
Instead of using 2 documents you may create a DocumentFragment of $article_htm2 and use this fragment as replacement.
I think it should be
$article->parentNode->replaceChild($article_old, $article_new);
the article is not a child of itself.

Categories