I have a string of 'source html' and a string of 'replacement html'. In the 'source html' I want to look for a node with a specific class and replace its content with my 'replacement html'. I have tried using the replaceChild method, but this seems to require that I traverse a level up (parentNode).
This doesn't work
$dom = new DOMDocument;
$dom->loadXml($sourceHTML);
$replacement = $dom->createDocumentFragment();
$replacement->appendXML($replacementHTML);
$xpath = new DOMXPath($dom);
$oldNode = $xpath->query('//div[contains(#class,"arrangement--index__field-dato")]')->item(0);
$oldNode->replaceChild($replacement, $oldNode);
This works, but it's not the content which is being replaced
$dom = new DOMDocument;
$dom->loadXml($sourceHTML);
$replacement = $dom->createDocumentFragment();
$replacement->appendXML($replacementHTML);
$xpath = new DOMXPath($dom);
$oldNode = $xpath->query('//div[contains(#class,"arrangement--index__field-dato")]')->item(0);
$oldNode->parentNode->replaceChild($replacement, $oldNode);
How do I replace the content or the node I have queried for?
Instead of replacing the child node, loop over it's children, drop them and insert the new content as child node. Something like
foreach ($oldNode->childNodes as $child)
$oldNode->removeChild($child);
$oldNode->appendChild($replacement);
This will replace the contents (children) instead of the node itself.
This seems to work!
$dom = new DOMDocument;
$dom->loadXml($sourceHTML);
$replacement = $dom->createDocumentFragment();
$replacement->appendXML($replacementHTML);
$xpath = new DOMXPath($dom);
$oldNode = $xpath->query('//div[contains(#class,"arrangement--index__field-dato")]')->item(0);
$oldNode->removeChild($oldNode->firstChild);
$oldNode->appendChild($replacement);
Related
I need to get span content from external url.
I managed to created a script working fine but not with the url i need, the result show the loading icon.
$html = file_get_contents('https://www.ryanair.com/fr/fr/booking/home/CRL/RAK/2019-03-24/2019-03-28/1/0/0/0');
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($html);
$finder = new DomXPath($doc);
$node = $finder->query("//*[contains(#class, 'flights-table-price__price')]");
print_r($doc->saveHTML($node->item(0)));
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).
I have a XML file and I'm trying to insert a new node between two others with PHP script.
XML file:
<playlistLog>
<hour>
<track>
<type>take</type>
<url>URL</url>
<title>1473869236.wav</title>
<mix>0</mix>
</track>
(...)
</hour>
</playlistLog>
PHP file:
$xmldoc = new DOMDocument();
$xmldoc->load('../logs/log14-09-2016.xml');
$elem = $xmldoc->getElementsByTagName("track");
$track = $xmldoc->createElement('track');
$type = $xmldoc->createElement('type', 'take');
$track->appendChild($type);
$url = $xmldoc->createElement('url', 'url');
$track->appendChild($url);
$title = $xmldoc->createElement('title', 'title');
$track->appendChild($title);
$mix = $xmldoc->createElement('mix', 'mix');
$track->appendChild($mix);
$xmldoc->documentElement->insertBefore($track,$elem[660]);
$xmldoc->save('../logs/log14-09-2016.xml');
I'm trying to insert the new node before "track" tag number 660 but when I try to open the php file it doesn't work at all.
Can anybody tell me what I am doing wrong?
SOLUTION:
After #ThW response I change a bit what he wrotes and finally the code is doing right:
$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->load('../logs/log14-09-2016.xml');
$xpath = new DOMXpath($document);
$previousTrack = $xpath->evaluate('/playlistLog/hour/track')->item(659);
$newTrack = $previousTrack->parentNode->insertBefore($document->createElement('track'),$previousTrack);
$newTrack
->appendChild($document->createElement('type'))
->appendChild($document->createTextNode('take'));
$document->formatOutput = TRUE;
echo $document->save('../logs/log14-09-2016.xml');
$elem[660] is the 661st element node with the tag name track. But its parent node is not the document element. Here is another hour ancestor between. The node you're providing to insertBefore() has a different parent then the node you're adding the new element to.
You can use the $parentNode property to make sure that you append to that node.
Additionally I suggest using Xpath to fetch the track node.
$xml = <<<'XML'
<playlistLog>
<hour>
<track>
<type>take</type>
<url>URL</url>
<title>1473869236.wav</title>
<mix>0</mix>
</track>
</hour>
</playlistLog>
XML;
$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$previousTrack = $xpath->evaluate('/playlistLog/hour/track[1]')->item(0);
$newTrack = $previousTrack
->parentNode
->insertBefore(
$document->createElement('track'),
$previousTrack
);
$newTrack
->appendChild($document->createElement('type'))
->appendChild($document->createTextNode('take'));
$document->formatOutput = TRUE;
echo $document->saveXml();
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>
from this xml file i want to delete picture node according to attribute id.
i have written php code but it does not work.
<gallery>
<organizate>
<organization w="3" h="1" space="17"/>
<organization w="4" h="2" space="17"/>
<organization w="6" h="3" space="7"/>
</organizate>
<pictures>
<picture target="events/preview/10picture1.jpg" title="test1" movie="" text="test1" link="events_calender.php" id="38"/>
<picture target="events/preview/8picture7.jpg" title="test2" movie="" text="cxvxc" link="events_calender.php" id="39"/>
<picture target="events/preview/5picture10.jpg" title="test3" movie="" text="test3" link="events_calender.php" id="40"/>
</pictures>
</gallery>
PHP code
$doc = new DOMDocument();
$doc->formatOutput = TRUE;
$doc->preserveWhiteSpace = FALSE;
$xPath = new DOMXPath($doc);
$doc->load('../Event_gallery.xml');
$query = sprintf('//pictures[./picture[#id="%s"]]', 38);
foreach ($xPath->query($query) as $node) {
$node->parentNode->removeChild($node);
}
$doc->save('../Event_gallery.xml');
I think xpath is not working properly. control is not going in foreach
The problem is you are loading the document after you pass the document to DOMXPath.
Change
$xPath = new DOMXPath($doc);
$doc->load('../Event_gallery.xml');
to
$doc->load('../Event_gallery.xml');
$xPath = new DOMXPath($doc);
Then it should work.
To remove just the picture element with the given id instead of the whole parent, change the XPath to
//pictures/picture[#id="38"]