XPath - displaying attributes - php

I have a following script:
<?php
$str = '<?xml version="1.0" encoding="utf-8"?>
<ROOT>
<ITEMS>
<BOOK>
<TITLE>Name 1</TITLE>
<AUTHOR>Author</AUTHOR>
<CATEGORY id="1">NOVEL</CATEGORY>
</BOOK>
<BOOK>
<TITLE>Name 2</TITLE>
<AUTHOR>Author</AUTHOR>
<CATEGORY id="2">MANUAL</CATEGORY>
</BOOK>
</ITEMS>
</ROOT>';
$xml = simplexml_load_string($str);
$category = $xml->xpath("/ROOT/ITEMS/BOOK/CATEGORY/text()");
print_r($category);
?>
I want to select all the categiries in xpath.
I tried also:
$category = $xml->xpath("/ROOT/ITEMS/BOOK/CATEGORY");
But my output is:
Array ( [0] => SimpleXMLElement Object ( [#attributes] => Array ( [id] => 1 ) ) [1] => SimpleXMLElement Object ( [#attributes] => Array ( [id] => 2 ) ) )
I don't want this output. I want to display NOVEL and MANUAL. I don't understand it, because I didn't use attribute command in xpath and I got it.
How to solve it? Thank you.

I have own solution. After few hours I have it! Thanks to your link in your answer. I read the examples and found how to get the right values.
<?php
$str = '<?xml version="1.0" encoding="utf-8"?>
<ROOT>
<ITEMS>
<BOOK>
<TITLE>Name 1</TITLE>
<AUTHOR>Author</AUTHOR>
<CATEGORY id="1">NOVEL</CATEGORY>
</BOOK>
<BOOK>
<TITLE>Name 2</TITLE>
<AUTHOR>Author</AUTHOR>
<CATEGORY id="2">MANUAL</CATEGORY>
</BOOK>
</ITEMS>
</ROOT>';
$xml = simplexml_load_string($str);
$category = $xml->xpath("/ROOT/ITEMS/BOOK/CATEGORY/text()");
while(list( , $node) = each($category)) {
echo $node."<BR />";
}
?>

When you use xpath return arrays is an array of SimpleXMLElement Objects (http://php.net/manual/ru/simplexmlelement.xpath.php), so they have their own structures. Somehow, you can iterate over this array and get all node values like this:
<?php
$str = '<?xml version="1.0" encoding="utf-8"?>
<ROOT>
<ITEMS>
<BOOK>
<TITLE>Name 1</TITLE>
<AUTHOR>Author</AUTHOR>
<CATEGORY id="1">NOVEL</CATEGORY>
</BOOK>
<BOOK>
<TITLE>Name 2</TITLE>
<AUTHOR>Author</AUTHOR>
<CATEGORY id="2">MANUAL</CATEGORY>
</BOOK>
</ITEMS>
</ROOT>';
$xml = simplexml_load_string($str);
$categories = $xml->xpath("/ROOT/ITEMS/BOOK/CATEGORY/text()");
foreach($categories as $category) {
echo "$category\n";
}

Related

PHP XML: Getting text of a node and its children

I know that this questions has been asked before, but I cannot make it work. I'm using simplexml and xpath in a PHP file. I need to get text from a node including the text in its child nodes. So, the results should be:
Mr.Smith bought a white convertible car.
Here is the xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test9.xsl"?>
<items>
<item>
<description>
<name>Mr.Smith bought a <car>white</car> <car>convertible</car> car.</name>
</description>
</item>
</items>
The php that's not working is:
$text = $xml->xpath('//items/item/description/name');
foreach($text as &$value) {
echo $value;
}
Please help!
To get the node value with all its child elements, you can use DOMDocument, with C14n():
<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test9.xsl"?>
<items>
<item>
<description>
<name>Mr.Smith bought a <car>white</car> <car>convertible</car> car.</name>
</description>
</item>
</items>
XML;
$doc = new DOMDocument;
$doc->loadXML($xml);
$x = new DOMXpath($doc);
$text = $x->query('//items/item/description/name');
echo $text[0]->C14n(); // Mr.Smith bought a white convertible car.
Demo

How to get value of xml element

I need to retrieve the value of the value of "TotalBooks" from an xml file that is structured like the example below.
I can get the equivalent of the "MatchesFound" value by doing a count of "book" and I can successfully get the information for each book.
However, I cannot get the actual value shown in the xml file for "MatchesFound", "TotalBooks", and "Page".
I'm using php with simplexml_load_file. Any help I can get is appreciated. Thanks.
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<MatchesFound>2</MatchesFound>
<TotalBooks>563</TotalBooks>
<Page>1</Page>
<book>
<title>Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price currency="USD">30.00</price>
</book>
<book>
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price currency="USD">29.99</price>
</book>
</bookstore>
$xml = new SimpleXMLElement($xmlString);
echo $xml->TotalBooks;
Using xpath :
<?php
$string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<MatchesFound>2</MatchesFound>
<TotalBooks>563</TotalBooks>
<Page>1</Page>
<book>
<title>Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price currency="USD">30.00</price>
</book>
<book>
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price currency="USD">29.99</price>
</book>
</bookstore>
XML;
$xml = new SimpleXMLElement($string);
$result = $xml->xpath('//TotalBooks');
while(list( , $node) = each($result)) {
echo "$node\n";
}
?>
See http://php.net/manual/en/simplexmlelement.xpath.php

PHP simplexml_load_string() - add child object to an object in a loop [duplicate]

This question already has answers here:
Is there a way to add a PHP SimpleXMLElement to another SimpleXMLElement?
(2 answers)
Closed 9 years ago.
So here is my code:
foreach($this->simpleXMLobject->path->toRecord->myRecord as $record)
{
$childXML = new \CurlClass\GetXML($record->link, $this->timeout);
$result = $childXML->get();
$xml = simplexml_load_string($result, NULL, LIBXML_NOCDATA);
if($xml !== FALSE)
{
$record->newChild = $xml->newChaldData;
}
}
As you can see i need to add Object to every $this->simpleXMLobject->path->toRecord->myRecord record.
And its not working!
In a print_r() of the final result i'm getting this:
[n] => SimpleXMLElement Object
(
[firstname] => ANGELA
[lastname] => LEE
[dob] => SimpleXMLElement Object
(
)
[id] => 67404998
[newChild] => SimpleXMLElement Object
(
[0] =>
)
)
I know that i have the XML in a $result.
Any ideas?
UPDATE:
The XMLs:
<xml>
<result>
<stats/>
<somadata/>
<somadata/>
<somadata/>
<crimeData>
<person>
<fName>Eric</fName>
<lName>Eric</lName>
<caseDetailed>data1</caseDetailes>
</person>
...
<person>
<fName>Eric</fName>
<lName>Eric</lName>
<caseDetailes>https://urltocasedetailes.com/blha/nlha</caseDetailes>
</person>
</crimeData>
</result>
https://urltocasedetailes.com/blha/nlha returns this kind of data:
<xml>
<result>
<stats/>
<detailesPart1>
<data1>Eric</data1>
<data2>Eric</data2>
</detailesPart1>
<detailesPart2>
<data1>Eric</data1>
<data2>Eric</data2>
</person>
</crimeData>
</result>
The idea is to get data from 'https://urltocasedetailes.com/blha/nlha' as xml object and add to the original xml <person> records
UPDATE
If i replace this:
if($xml !== FALSE)
{
$record->newChild = $xml->newChaldData;
}
With this:
if($xml !== FALSE)
{
$record->newChild = $xml->newChaldData->child1;
}
It works! But that's not really what i need.
I'll take your mockup XMLs and try to exemplify how to add specific data to the original XML, hope this will help you:
<?php
$originalXML = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<result>
<crimeData>
<person>
<fName>Eric</fName>
<lName>Eric</lName>
<caseDetailes>https://urltocasedetailes.com/blha/nlha</caseDetailes>
</person>
</crimeData>
</result>
XML;
$childXML = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<result>
<crimeData>
<person>
<detailesPart1>
<data1>Eric</data1>
<data2>Eric</data2>
</detailesPart1>
<detailesPart2>
<data1>Eric</data1>
<data2>Eric</data2>
</detailesPart2>
</person>
</crimeData>
</result>
XML;
$sxe = new SimpleXMLElement($originalXML);
$persons = $sxe->xpath('//person');
foreach ($persons as $person) {
$url = (string) $person->caseDetailes;
// Retrieve the XML from the external location from caseDetailes
// $childSxe = new SimpleXMLElement($url, 0, true);
// Using this just for the example purpose
$childSxe = new SimpleXMLElement($childXML);
// Retrieve detailesPart2 from your external XML
$detailes = $childSxe->xpath('//detailesPart2');
// Add detailesPart2/data1 to the person record
foreach ($detailes as $detaile) {
$person->addChild($detaile->data1->getName(), (string) $detaile->data1);
}
}
echo $sxe->asXML();
Output:
<?xml version="1.0" encoding="UTF-8"?>
<result>
<crimeData>
<person>
<fName>Eric</fName>
<lName>Eric</lName>
<caseDetailes>https://urltocasedetailes.com/blha/nlha</caseDetailes>
<data1>Eric</data1>
</person>
</crimeData>
</result>

cloneNode + appendChild + insertBefore dom xml php

I have an xml and I would be cloning father and leave under the cloned node.
More giving this error.
I wonder how
Fatal error: Call to a member function insertBefore() on a non-object in C:\xampp\htdocs\xml2\cloneNew.php on line 32
$xmla = <<<XML
<?xml version="1.0" ?>
<library>
<book isbn="1001" pubdate="1943-01-01">
<title><![CDATA[The Fountainhead]]></title>
<author>Ayn Rand</author>
<price>300</price>
</book>
<book isbn="1002" pubdate="1954-01-01">
<title><![CDATA[The Lord of the Rings]]></title>
<author>J.R.R.Tolkein</author>
<price>500</price>
</book>
<book isbn="1006" pubdate="1982-01-01">
<title><![CDATA[The Dark - Tower San]]></title>
<author>Stephen King</author>
<price>200</price>
</book>
</library>
XML;
$xmlb = <<<XML
<?xml version="1.0" ?>
<library>
<book isbn="1004" pubdate="1943-01-01">
<title><![CDATA[The Fountainhead]]></title>
<author>Ayn Rand</author>
<price>300</price>
</book>
</library>
XML;
$dom_01 = new DOMDocument();
$dom_01->loadXML($xmla);
$library_01 = $dom_01->documentElement;
$dom_02 = new DOMDocument();
$dom_02->loadXML($xmlb);
$library_02 = $dom_02->documentElement;
$xpath = new DOMXPath($dom_02);
$result = $xpath->query('/library/book[translate(#pubdate,"-","")>translate("1980-01-01","-","")]');
$library_02 = $library_02->cloneNode(true);
$newElement = $library_01->appendChild($result->item(0));
$library_01->parentNode->insertBefore($newElement, $result->item(0));
header("Content-type: text/xml");
echo $dom->saveXML();
Result:
$xmla = <<<XML
<?xml version="1.0" ?>
<library>
<book isbn="1001" pubdate="1943-01-01">
<title><![CDATA[The Fountainhead]]></title>
<author>Ayn Rand</author>
<price>300</price>
</book>
<book isbn="1002" pubdate="1954-01-01">
<title><![CDATA[The Lord of the Rings]]></title>
<author>J.R.R.Tolkein</author>
<price>500</price>
</book>
<book isbn="1004" pubdate="1943-01-01">
<title><![CDATA[The Fountainhead]]></title>
<author>Ayn Rand</author>
<price>300</price>
</book>
<book isbn="1006" pubdate="1982-01-01">
<title><![CDATA[The Dark - Tower San]]></title>
<author>Stephen King</author>
<price>200</price>
</book>
</library>
XML;
You are trying to get the parentNode of a documentElement no such node exists.
Also if you want to place a node from one document into another use DOMDocument.importNode instead of cloneNode.

Renaming a DOMNode in PHP

<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<Document xmlns='urn:iso:std:iso:20022:tech:xsd:pain.001.001.02'>
<books>
<book>
<qty>12</qty>
<title>C++</title>
</book>
<book>
<qty>21</qty>
<title>PHP</title>
</book>
</books>
<books>
<book>
<qty>25</qty>
<title>Java</title>
</book>
<book>
<qty>32</qty>
<title>Python</title>
</book>
<book>
<qty>22</qty>
<title>History</title>
</book>
</books>
</Document>
How Can I Rename ?
<Document xmlns='urn:iso:std:iso:20022:tech:xsd:pain.001.001.02'>
TO
<Document>
here you don't rename, you remove an attribute. Maybe DomElement::removeAttribute (http://php.net/manual/en/domelement.removeattribute.php) will do the work BUT if he doesn't because xmlns defines a namespace try to redefine the default namespace to null.

Categories