XPath and PHP troubleshooting - php

I get this error:
Notice: Trying to get property of non-object in
Applies to:
echo $result->Data;
And this output:
Array ()
Background Informations
A function returns a string which contains an XML file.
I want to get some data from two tags and deal with them on their own.
String Data
$data="
<SyncML xmlns='SYNCML:SYNCML1.0'>
<SyncHdr>
</SyncHdr>
<SyncBody>
<betameta>
WANT 1
</betameta>
<Add>
<Data>
WANT 2
</Data>
</Add>
</SyncBody>
</SyncML>";
In the above data, I want values "WANT 1" and "WANT 2"
Code so far
$xml = simplexml_load_string($data);
$result = $xml->xpath("/SyncML/SyncBody");
print_r($result);
echo $result->Data;

$xml->registerXPathNamespace('default','SYNCML:SYNCML1.0');
$result = $xml->xpath("/default:SyncML/default:SyncBody");

Remove the trailing slash.

The only solution I can find is the following:
<?php
$data= <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<SyncML>
<SyncHdr>
</SyncHdr>
<SyncBody>
<betameta>
WANT 1
</betameta>
<Add>
<Data>
WANT 2
</Data>
</Add>
</SyncBody>
</SyncML>
XML;
$xml = simplexml_load_string($data);
$result = $xml->xpath("/SyncML/SyncBody");
print_r($result);
echo $result;
is there anyway you can loose the xmlns?
This will output:
Array
(
[0] => SimpleXMLElement Object
(
[betameta] =>
WANT 1
[Add] => SimpleXMLElement Object
(
[Data] =>
WANT 2
)
)
)

Related

each node attribute value of xml in php

Im trying to get the catId value. But i can see only the category value.
My xml file looks below:
<sample>
<Item ItemNumber="00000088" FormattedItemNumber="00000-088">
<CompatibleModels />
<Category CatId="160" > test 123 </Category>
<Images />
<Documents />
<RequiredItems />
</Item>
</sample>
$xml = simplexml_load_file("test.xml");
print_r($xml);
[sample] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[ItemNumber] => 00000088
[FormattedItemNumber] => 00000-088
)
[Category] => Bags/Luggage 123
)
how can get the CatId value? Why the cateId value is missing?
You can do it by many ways. Let's try-
foreach ($xml as $items) {
echo $items->Category['CatId'];
}
WORKING DEMO: https://3v4l.org/Onqe2
print_r doesn't really work with SimpleXML objects. But from the sample data you have provided you can simply access the CatId attribute using
echo $xml->Item->Category['CatId'];
You can loop and get it by using following snippet, please refer inline documentation for explanation
$xml1 = simplexml_load_file("test.xml") or die("Error: Cannot create object");
foreach ($xml1->children() as $items1) { // children mean item
echo ($items1->category['catid']); // for category tag get catid attribute
}

Getting an entire value from XML

How do I get the entire result from XML using simplexml_load_string?
My XML looks like this
<xml>
<code>
<codedesc>Code Name</codedesc>
100
</code>
<code>
<codedesc>Code Name 2</codedesc>
200
</code>
</xml>
When I load it with PHP using this code
$XML = simplexml_load_string($data);
print_r($XML);
I only get codedesc and not the code number as you can see here
https://eval.in/51562
You need to wrap your values in XML so that they can be accessed.
<xml>
<code>
<codedesc>Code Name</codedesc>
<value>100</value>
</code>
<code>
<codedesc>Code Name 2</codedesc>
<value>200</value>
</code>
</xml>
You can then access them like so:
$xml = simplexml_load_string($data);
echo $xml->code[0]->value; //100
echo $xml->code[1]->value; //200
echo $xml->code[1]->codedesc; //Code Name 2
If you can't change your xml, the following should work:
echo $xml->code[0]; //100
echo $xml->code[1]; //200
I'm not sure what you're trying to get SimpleXML correctly parses your XML string, and returns a class with an array called 'code', that has 2 objects called codedesc:
SimpleXMLElement Object
(
[code] => Array
(
[0] => SimpleXMLElement Object
(
[codedesc] => Code Name
)
[1] => SimpleXMLElement Object
(
[codedesc] => Code Name 2
)
)
)
If you're trying to get to the values (100, 200) - try putting them in XML elements.
If you're trying to print the entire XML, try print_r($XML->asXML()) (see this)

How to get all node values from a feed

I have following feed:
$result = apiCall('somevalue', 'somevalue', array('somevalue' => $some_string));
which is in json format. I can very easy to turn it into xml with
$xml = simplexml_load_string($result);
The xml feed looks as follow:
<?xml version="1.0" encoding="ISO-8859-15"?>
<response>
<status>success</status>
<code>200</code>
<message>
<a>
<g>val1</g>
<b>val2</b>
<c>val3</c>
</a>
<d>
<e>val4</e>
<f>val5</f>
</d>
</message>
</response>
Is there a simple and fast way to get all node values (i.e. val1, val2, val3, val4, val5 and so on)?
I wrote something that I think will work:
<?php
$xml = <<<EOD
<?xml version="1.0" encoding="ISO-8859-15"?>
<response>
<status>success</status>
<code>200</code>
<message>
<a>
<g>val1</g>
<b>val2</b>
<c>val3</c>
</a>
<d>
<e>val4</e>
<f>val5</f>
</d>
</message>
</response>
EOD;
$output = array();
$test = simplexml_load_string($xml);
$result = $test->xpath('message//*[not(*)]');
while(list(, $node) = each($result)) {
array_push($output, (string) $node);
}
var_dump($output);
?>
I haven't tested it on a lot of things (attributes), but on the provided input it gives the expected output.
What it does is like you can see an xpath expression that retrieves any child of the message node.
Of course, since there are also nodes with even more childnodes in it (like aand d) we need to filter those out. So the last part containing the not(*) means that it will only select those childs which do not have any sub child.
I'm not an XPATH expert so there are probably faster ways of achieving this, but I think this will do.
I came to a similar conclusion like Dimitri M, it's based on a previous Q&A How to select all leaf nodes using XPath expression?.
Leaf-Nodes are the outermost nodes, which are those you're looking for, here the text() nodes in your case.
$nodeValues = array_map(
'trim',
simplexml_load_string($xml)->xpath('message//*[not(*)]/text()')
);
Given that $xml is your XML input, $nodeValues is then an array of all those strings that represent the node values you're looking for. Exemplary:
Array
(
[0] => val1
[1] => val2
[2] => val3
[3] => val4
[4] => val5
)

Reading a XML File in PHP

I am importing a XML file that has an amount field <amount>$10.00</amount> but when it is read in using code I got from your other posts, the value is returned as .00.
Using:
$xml = simplexml_load_file("testInput.xml");
print_r($xml);
Result:
[amount] => .00
I can't find anywhere why this is failing... Unless it has to do with the $ or period in the value field but I can't find anything about reserved characters.
I tried to duplicate your results and couldn't...
I created a file called xml_test.php:
<?php
$xml = simplexml_load_file('test_input.xml');
print_r($xml);
?>
Then built the XML (test_input.xml):
<?xml version="1.0" encoding="UTF-8"?>
<tests>
<test>
<amount>$10.00</amount>
</test>
</tests>
And this was my result in the browser:
SimpleXMLElement Object ( [test] => SimpleXMLElement Object ( [amount] => $10.00 ) )
Is there anything else going on or am I missing something? Maybe you can paste in your XML...

display data from XML using php simplexml

I have a piece of XML which is as follows
<records count="2">
<record>
<firstname>firstname</firstname>
<middlename>middlename</middlename>
<lastname>lastname</lastname>
<namesuffix/>
<address>
<street-number>demo</street-number>
<street-pre-direction/>
<street-name>demo</street-name>
<street-post-direction/>
<street-suffix>demo</street-suffix>
<city>demo</city>
<state>NY</state>
<zip>demo</zip>
<zip4>demo</zip4>
<county>demo</county>
</address>
<phonenumberdetails>
<phonenumber>demo</phonenumber>
<listed>demo</listed>
<firstname>demo</firstname>
</phonenumberdetails>
<dob day="" month="" year=""/>
<age/>
<date-first month="10" year="1999"/>
<date-last month="04" year="2011"/>
</record>
<record>
<firstname>firstname</firstname>
<middlename>middlename</middlename>
<lastname>lastname</lastname>
<namesuffix/>
<address>
<street-number>demo</street-number>
<street-pre-direction/>
<street-name>demo</street-name>
<street-post-direction/>
<street-suffix>demo</street-suffix>
<city>demo</city>
<state>NY</state>
<zip>demo</zip>
<zip4>demo</zip4>
<county>demo</county>
</address>
<phonenumberdetails>
<phonenumber>demo</phonenumber>
<listed>demo</listed>
<firstname>demo</firstname>
</phonenumberdetails>
<dob day="" month="" year=""/>
<age/>
<date-first month="10" year="1999"/>
<date-last month="04" year="2011"/>
</record>
</records>
Now, I have been able to get all the data in PHP using SimpleXML except for the date-first and date-last elements. I have been using code listed below
$dateFirst = 'date-first';
$dateLast = 'date-last';
$streetNumber = 'street-number';
$streetPreDirection = 'street-pre-direction';
$streetName = 'street-name';
$streetPostDirection = 'street-post-direction';
$streetSuffix = 'street-suffix';
$unitDesignation = 'unit-designation';
$unitNumber = 'unit-number';
foreach ($reportDataXmlrecords->records->record as $currentRecord) {
echo $currentRecord->$dateFirst['month'].'/'.$currentRecord->$dateFirst['year'];
echo $currentRecord->$dateLast['month'].'/'.$currentRecord->$dateLast['year'];
echo $currentRecord->address->$streetNumber;
$currentRecord->address->$streetName; // ......and so on
}
where $reportDataXmlrecords is the part of the simpleXML object from the parent node of
But the first two echo's don't print anything and all the other are printing correctly, specifically, I cant access the data in
<date-first month="10" year="1999"/>
<date-last month="04" year="2011"/>
Also for debugging if I do
print_r($currentRecord->$dateFirst);
it prints
SimpleXMLElement Object (
[#attributes] => Array ( [month] => 10 [year] => 1999 )
)
Any help would be greatly appreciated. Thank you.
You problem is when you do
$currentRecord->$dateFirst['month']
PHP will first evaluate $dateFirst['month'] as a whole before trying to use it as a property
$dateFirst = 'date-first';
var_dump( $dateFirst['month'] ); // gives "d"
because strings can be accessed by offset with array notation, but non-integer offsets are converted to integer and because casting 'month' to integer is 0, you are trying to do $currentRecord->d:
$xml = <<< XML
<record>
<date-first month="jan"/>
<d>foo</d>
</record>
XML;
$record = simplexml_load_string($xml);
$var = 'date-first';
echo $record->$var['month']; // foo
You can access hyphenated properties with curly braces:
$record->{'date-first'}['month'] // jan
On a sidenote, when the XML shown in your question is really the XML you are loading with SimpleXml, e.g. when <records> is the root node, then doing
$reportDataXmlrecords->records->record
cannot work, because $reportDataXmlrecords is already the root node and you'd have to omit the ->records if you want to iterate over the record elements in it.

Categories