i'm struggling with Xpath, i have an xml list and i need to get the child data based on the parent id ...
My xml file :
<projecten>
<project id="1">
<titel>Shop 1</titel>
<siteurl>http://test.be</siteurl>
<screenshot>test.jpg</screenshot>
<omschrijving>comment 1</omschrijving>
</project>
<project id="2">
<titel>Shop 2</titel>
<siteurl>http://test2.be</siteurl>
<screenshot>test2.jpg</screenshot>
<omschrijving>comment</omschrijving>
</project>
</projecten>
the code i use to get for example the project 1 data (does not work):
$xmlDoc = new DOMDocument();
$xmlDoc->load(data.xml);
$xpath = new DOMXPath($xmlDoc);
$projectId = '1';
$query = '//projecten/project[#id='.$projectId.']';
$details = $xpath->query($query);
foreach( $details as $detail )
{
echo $detail->titel;
echo $detail->siteurl;
echo $detail->screenshot;
echo $detail->omschrijving;
}
But this does not show anything, if someone can point me out ... thanks
In addition to the solution already given you can also use:
foreach ($xpath->query(sprintf('/projecten/project[#id="%d"]', $id)) as $projectNode) {
echo
$projectNode->getElementsByTagName('titel')->item(0)->nodeValue,
$projectNode->getElementsByTagName('siteurl')->item(0)->nodeValue,
$projectNode->getElementsByTagName('screenshot')->item(0)->nodeValue,
$projectNode->getElementsByTagName('omschrijving')->item(0)->nodeValue;
}
or fetch the DOMText node values directly with Xpath
foreach ($xpath->query(sprintf('/projecten/project[#id="%d"]', $id)) as $projectNode) {
echo
$xpath->evaluate('string(titel)', $projectNode),
$xpath->evaluate('string(siteurl)', $projectNode),
$xpath->evaluate('string(screenshot)', $projectNode),
$xpath->evaluate('string(omschrijving)', $projectNode);
}
or import the node to SimpleXml
foreach ($xpath->query(sprintf('/projecten/project[#id="%d"]', $id)) as $projectNode) {
$detail = simplexml_import_dom($projectNode);
echo
$detail->titel,
$detail->siteurl,
$detail->screenshot,
$detail->omschrijving;
}
or even concatenate all the values directly in the XPath:
$xpath = new DOMXPath($dom);
echo $xpath->evaluate(
sprintf(
'concat(
/projecten/project[#id = %1$d]/titel,
/projecten/project[#id = %1$d]/siteurl,
/projecten/project[#id = %1$d]/screenshot,
/projecten/project[#id = %1$d]/omschrijving
', $id
)
);
Accessing the child nodes as you do:
echo $detail->title;
Is not valid, if you use DOM* functions. This would probably work if you were using SimpleXML.
For DOM* try this:
$dom = new DOMDocument;
$dom->loadXml('<projecten>
<project id="1">
<titel>Shop 1</titel>
<siteurl>http://test.be</siteurl>
<screenshot>test.jpg</screenshot>
<omschrijving>comment 1</omschrijving>
</project>
<project id="2">
<titel>Shop 2</titel>
<siteurl>http://test2.be</siteurl>
<screenshot>test2.jpg</screenshot>
<omschrijving>comment</omschrijving>
</project>
</projecten>
');
$id = 2;
$xpath = new DOMXPath($dom);
foreach ($xpath->query(sprintf('/projecten/project[#id="%s"]', $id)) as $projectNode) {
// repeat this for every needed node
$titleNode = $xpath->query('titel', $projectNode)->item(0);
if ($titleNode instanceof DOMElement) {
echo $titleNode->nodeValue;
}
// or us a loop for all child nodes
foreach ($projectNode->childNodes as $childNode) {
echo $childNode->nodeValue;
}
}
Related
I have all properties listed in XML file with this structure
<property>
<details>
<object>25.5 m2 Flat in New York</object>
</details>
</property>
<property>
<details>
<object>95.6 m2 House in New Jersey</object>
</details>
</property>
Now I want to use PHP to find the node with a specific <object> value and to remove the parent node (<property>). How can I do it?
I tried by doing the code below but I cannot manage to work.
$doc = new DOMDocument;
$doc->load('../openimmo/xml-import1.xml');
$thedocument = $doc->documentElement;
$list = $thedocument->getElementsByTagName('property');
$nodeToRemove = null;
foreach ($list as $domElement) {
$attrValue = $domElement->getElementsByTagName('object');
foreach ($attrValue as $item) {
if ($item->nodeValue == $_GET['delete']) {
$nodeToRemove = $domElement;
}
}
}
if ($nodeToRemove != null)
$thedocument->removeChild($nodeToRemove);
echo $doc->saveXML();
You can use Xpath expressions to fetch nodes. This allows you to use conditions.
$document = new DOMDocument;
//$document->load('../openimmo/xml-import1.xml');
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$objectText = '25.5 m2 Flat in New York';
$properties = $xpath->evaluate('//property[details/object = "'.$objectText.'"]');
foreach ($properties as $property) {
// remove the node (PHP 8)
$property->remove();
}
echo $document->saveXML();
The other difference is that the result of DOMXpath::evaluate() is not live. Unlike the result from DOMNode::getElementsByTagName() it does not change if the DOM changes.
PHP 8 adds DOM Living Standard methods. In PHP 7 you would have to use $property->parentNode->removeChild($property).
I am trying to search an XML file of the following structure:
<Root>
<Record>
<Filenumber>12314123</Filenumber>
<StatusEN>Closed</StatusEN>
<StatusDate>02 Nov 2019</StatusDate>
</Record>
<Record>
<Filenumber>0678672301</Filenumber>
<StatusEN>Closed</StatusEN>
<StatusDate>02 Nov 2019</StatusDate>
</Record>
</Root>
I want to search based on the filenumber, but return all 3 nodes and values for the match.
I am trying
$q = '12314123';
$file = "status.xml";
$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->Load($file);
$xpath = new DOMXPath($doc);
$query = "/Root/Record/Filenumber[contains(text(), '$q')]";
$entries = $xpath->query($query);
foreach ($entries as $entry) {
echo $entry->parentNode->nodeValue ;
}
This seems to return all the values I want but in one single string. How can I return them as separate variables or even better, in an array or JSON?
DOMNodeList or DOMNodeElement don't know how become an array. And that's why we must do it with our hands:
foreach ($entries as $entry) {
$result = [];
foreach ($entry->parentNode->childNodes as $node) {
$result[$node->nodeName] = $node->nodeValue;
}
var_dump($result);
}
Have tried numerous examples on SO but none have worked.
Goal: Remove a node (unit) and it's children, by specific id=
filename.xml
<archive>
<unit id="0424670018">
<data>Blah blah blah #1</data>
<gdate>2018-05-28 00:42:46</gdate>
</unit>
<unit id="0450170018">
<data>Blah blah blah #2</data>
<gdate>2018-05-28 00:45:01</gdate>
</unit>
</archive>
Code used, not sure why it does not work when loaded:
$id = '0450170018';
$file = 'filename.xml';
$xml = simplexml_load_string($file);
foreach($xml->archive as $fileload){
if($fileload->unit['#id'] == $id){
$dom = dom_import_simplexml($fileload);
$dom->parentNode->removeChild($dom);
}
}
You can fetch the node using Xpath. It allows to fetch the matching node(s) directly.
$id = '0450170018';
$document = new DOMDocument();
$document->load('filename.xml');
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate("//unit[#id='$id']") as $unitNode) {
$unitNode->parentNode->removeChild($unitNode);
}
$document->save('filename.xml');
You need to use "DOMDocument" class
$doc = new DOMDocument;
$doc->load('filename.xml');
$xml = $doc->documentElement;
$id = '0450170018';
$domNodeList = $xml->getElementsByTagname('unit');
foreach ( $domNodeList as $domElement ) {
$valueID = $domElement->getAttribute('id');
if($valueID == $id)
{
$xml->removeChild($domElement);
}
}
$doc->save('filename.xml');
Using the following xml: http://www.bnr.ro/nbrfxrates.xml
How can I get the EUR value?
Been trying like this ... but no luck.
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.bnr.ro/nbrfxrates.xml');
$searchNode = $xmlDoc->getElementsByTagName("Cube");
var_dump($searchNode);
foreach ($searchNode as $searchNode) {
$valueID = $searchNode->getAttribute('Rate');
echo $valueID;
}
Check this
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.bnr.ro/nbrfxrates.xml');
foreach ($xmlDoc->getElementsByTagName('Rate') as $searchNode) {
if($searchNode->getAttribute('currency') === 'EUR') {
echo $searchNode->nodeValue;
}
}
?>
First Rate is not an attribute but an element. So you would need another getElementsByTagName('Rate') and loop over it. However the XML uses a default namespace so getElementByTagNameNS('http://www.bnr.ro/xsd', 'Rate') would be the correct way.
An easier way is to use Xpath to fetch the value directly:
$document = new DOMDocument();
$document->load('http://www.bnr.ro/nbrfxrates.xml');
$xpath = new DOMXpath($document);
$xpath->registerNamespace('r', 'http://www.bnr.ro/xsd');
var_dump(
$xpath->evaluate('number(//r:Cube/r:Rate[#currency="EUR"])')
);
Output:
float(4.4961)
Xpath does not have a default namespace, so you have to register your own alias for it (I used r in the example.).
The Xpath expression
fetch any {http://www.bnr.ro/nbrfxrates.xml}Cube
//r:Cube
fetch all {http://www.bnr.ro/nbrfxrates.xml}Rate children
//r:Cube/r:Rate
filter by the currency attribute
//r:Cube/r:Rate[#currency="EUR"]
cast the first found node into a number
number(//r:Cube/r:Rate[#currency="EUR"])
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.bnr.ro/nbrfxrates.xml');
foreach($xmlDoc->getElementsByTagName("Rate") as $node)
{
$currency = $node->getAttribute('currency');
if($currency == 'EUR')
{
$value = $node->nodeValue;
}
}
echo 'value for EUR is - '. $value;
?>
http://pastebin.com/hXuHpcUQ
Is what I have..
How can I load and read the data?
so for each node, I could do something like:
foreach($nodes as $node)
{
echo $node->getElementsByTagName("url") . "<br />";
}
But how should $nodes be defined to grab alle the <node type="link">'s?
This is what I have started out and currently got:
$doc = new DOMDocument();
try
{
$doc = new DOMDocument();
$doc->loadXml(file_get_contents('new.xml'));
}catch(Exception $e)
{
continue;
}
I would like to output the value in <url> inside each <node></node> element
I would use SimpleXML - should be something like.
$xml = simplexml_load_file('new.xml');
foreach ($xml->node as $node) {
echo $node->url;
}
(untested..)
You should read about DOMXPath
Your query will look like (not tested):
$nodes = $xpath_obj->query("//node[type='link']/url");