PHP - get values from xml - php

I have a some problem with get value from xml.
XML look like
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://crd.gov.pl/xml/schematy/UPO/2008/05/09/UPO.xsl"?>
<pos:Document xmlns:pos="SOMEURL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<pos:DescribeDoc/>
<pos:UPD>
<pos:IdDoc>procotol-UPD2198338</pos:IdDoc>
<pos:IdCases>221872</pos:IdCases>
<pos:additionalInfo TypeInfo="Source">Some string</pos:additionalInfo>
</pos:UPD>
...
I general try to get to pos:IdCases.
I try this code:
$domContent = new SimpleXMLElement(((string) $content), LIBXML_COMPACT);
$test = $domContent->xpath('/pos:Document/pos:UPD/*');
foreach($test as $node){
print_r($node)
}
I get a some object such as
SimpleXMLElement Object
(
[0] => procotol-UPD2198338
)
SimpleXMLElement Object
(
[0] => 221872
)
SimpleXMLElement Object
(
[#attributes] => Array
(
[TypeInfo] => Source
)
[0] => Some string
)
But I must get to pos:IdCases. I can't use index [1] because order can change.
My question is:
How can I get to value in node: pos:IdCases
I can't add id or another info to node because this xml was signed (XADES).
Can you give me some advice? Thanks for help

Simply change the XPath to match the <Pos:IdCases/> node:
$test = $domContent->xpath('/pos:Document/pos:UPD/pos:IdCases');

Related

Remove XML child with same name

I have a large XML with the following:
<?xml version="1.0" encoding="UTF-8"?>
<valasz xmlns="" verzio="1.0">
<arak>
<ar>
<cikkid>439902</cikkid>
<cikkszam>DVDV-16Z10</cikkszam>
<listaar>1225,0000000</listaar>
<ar>1157,6200000</ar>
<akcios_ar>1157,6200000</akcios_ar>
<devizanem>HUF</devizanem>
</ar>
<ar>
..
<ar>1157,6200000</ar>
...
</ar>
</arak>
What i want is to remove arak->ar->ar child because its causing in the import it looks like duplicates, and slowing down the process.
I have tried the following:
$node = readfile($arlista[0]);
$nodes = simplexml_load_string($node);
$arnode = $nodes->xpath("/valasz/arak/ar/ar");
foreach ($arnode as &$ar){
$nodes->removeChild($ar);
}
echo $nodes;
And this only returns me the original xml, without removing the arak->ar->ar child nodes.
What am i doing wrong?
There is no such thing as ::removeChild() in SimpleXML.
What you want do do in your foreach loop is this:
foreach ($arnode as $ar){
unset($ar->{0});
}
Please note: The posted XML is not valid but I am sure that is just some kind of copy&paste flaw
Complete code:
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<valasz xmlns="" verzio="1.0">
<arak>
<ar>
<cikkid>439902</cikkid>
<cikkszam>DVDV-16Z10</cikkszam>
<listaar>1225,0000000</listaar>
<ar>1157,6200000</ar>
<akcios_ar>1157,6200000</akcios_ar>
<devizanem>HUF</devizanem>
</ar>
<ar>
<ar>1157,6200000</ar>
</ar>
</arak>
</valasz>';
$nodes = simplexml_load_string($xml);
$arnode = $nodes->xpath("/valasz/arak/ar/ar");
foreach ($arnode as $ar){
unset($ar->{0});
}
print_r($nodes);
Returns this
SimpleXMLElement Object
(
[#attributes] => Array
(
[verzio] => 1.0
)
[arak] => SimpleXMLElement Object
(
[ar] => Array
(
[0] => SimpleXMLElement Object
(
[cikkid] => 439902
[cikkszam] => DVDV-16Z10
[listaar] => 1225,0000000
[akcios_ar] => 1157,6200000
[devizanem] => HUF
)
[1] => SimpleXMLElement Object
(
)
)
)
)

simplexmlelement array to <xml file format

let say my code below is a xml object code
SimpleXMLElement Object
(
[data] => SimpleXMLElement Object
(
[delivery_info] => SimpleXMLElement Object
(
[carriage_list] => SimpleXMLElement Object
(
[carriage] => SimpleXMLElement Object
(
[name] => aa
[price] => 0.00
)
)
now need convert it to example below
<?xml version='1.0'?>
<document>
<data>
<delivery_info>
<carriage_list>
<carriage>
<name>aa</name>
<price>aa</price>
</carriage>
</carriage_list>
</delivery_info>
</data>
</document>
XML;
so how i do it? i got search many time already ,no any answer to me
pls help thanks
You can use asXML($filename) function of SimpleXMLElement or cast type to string if you don't need to save to file:
$xml = (string) $element;

GPX file parse with PHP, get <extensions> element values

i have xml/gpx file:
<?xml version="1.0" encoding="utf-8"?>
<gpx xsi:schemaLocation="http://www.topografix.com/GPX/1/1">
<metadata>
....
</metadata>
<trk>
<trkseg>
<trkpt lat="50.04551333333333" lon="14.434101666666667">
<ele>282</ele>
<time>2014-06-30T20:56:03.92</time>
<extensions>
<gpxtpx:TrackPointExtension>
<gpxtpx:hr>100</gpxtpx:hr>
</gpxtpx:TrackPointExtension>
</extensions>
</trkpt>
...
</gpx>
Load:
$xml=simplexml_load_file($gpx_file);
parse witch
foreach($xml->trk->trkseg->trkpt as $point){}
Thats fine. But i cant get content of /extension//extension/
print_r($point) is
SimpleXMLElement Object
(
[#attributes] => Array
(
[lat] => 50.04527
[lon] => 14.433993333333333
)
[ele] => 280.5
[time] => 2014-06-30T20:57:21.71
[extensions] => SimpleXMLElement Object
(
)
)
and i cannot get SimpleXMLElement Object.
Print_r($point->extension is:
SimpleXMLElement Object
(
)
I try Converting a SimpleXML Object to an Array and other similiar way, but i have failed - output is empty array.
Any idea/way to get into string/array ?
Sample gpx is on www.vovcinec.net/gpx/e.gpx (~700kB)
You can't get them directly since they are in namespaces, you need to use getNamespaces() method first. Consider this example:
$xml = simplexml_load_file('e.gpx');
foreach($xml->trk->trkseg->trkpt as $trkpt) {
$namespaces = $trkpt->getNamespaces(true);
$gpxtpx = $trkpt->extensions->children($namespaces['gpxtpx']);
$hr = (string) $gpxtpx->TrackPointExtension->hr;
echo '<pre>';
print_r($hr);
echo '</pre>';
}
I hope you help following code
foreach($gpx->trk->trkseg->children() as $trkpts) {
echo (string)$trkpts->extensions->children('gpxtpx',true)->TrackPointExtension->hr;
}
no need to use getNamespaces() method

How to get an element from simplexml [duplicate]

This question already has answers here:
SimpleXML get node value
(3 answers)
Closed 8 years ago.
SimpleXMLElement Object
(
[SMSMessage] => SimpleXMLElement Object
(
[Sid] => xyz
[DateUpdated] => 2013-05-02 18:43:19
[DateCreated] => 2013-05-02 18:43:19
[DateSent] => 1970-01-01 05:30:00
[AccountSid] => xx
[To] => 09011148771
[From] => xx
[Body] => Hello
[BodyIndex] => SimpleXMLElement Object
(
)
[Status] => sending
[Direction] => outbound-api
[Price] => SimpleXMLElement Object
(
)
[ApiVersion] => SimpleXMLElement Object
(
)
[Uri] => /v1/Accounts/xx/Sms/Messages/xyz
)
)
I tried:
$xml->Sid;
But it returns SimpleXMLElement Object ( )
I also tried $xml->title, which also returned the same SimpleXMLElement Object ( )
How to get the Sid from the above XMl
I've been Fiddling a bit and recreated a structure similar to yours:
$string='<?xml version="1.0"?>
<xml>
<SMSMessage>
<Sid>xyz</Sid>
<DateUpdated>2013-05-02 18:43:19</DateUpdated>
</SMSMessage>
</xml>';
$xml = new SimpleXMLElement($string);
print_r($xml);
this outputs:
SimpleXMLElement Object
(
[SMSMessage] => SimpleXMLElement Object
(
[Sid] => xyz
[DateUpdated] => 2013-05-02 18:43:19
)
)
Which is equal to yours. And I could print xyz doing:
echo $xml->SMSMessage->Sid;
Try it out, you might be missing some parent node or something.
Your Method: To do it the way you want, I think you'd have to go one step further with your call since the SimpleXMLObject is parent to another SimpleXMLObject. E.g. $xml->SMSMessage->Sid;. I generally recommend using xpath with XML because in most cases, you want to jump directly to a specific node and not traverse the whole XML tree. For example, this: $xml->xpath('//[node]') is quicker than $xml->tier1->tier2->tier3->etc.
Preferred Method: Assuming $xml represents the SimpleXMLObject you've posted, you can access Sid like this: $xml->xpath('//Sid');. This should skip directly to the "Sid" node in the tree.
In simplexml you always have to cast your values - so you have to do this:
echo $xml->Sid;
(echo automatically casts). Or explicitly:
$string = (string) $xml->id;
if you have:
$string='<?xml version="1.0"?>
<xml>
<SMSMessage>
<Sid>xyz</Sid>
<DateUpdated>2013-05-02 18:43:19</DateUpdated>
</SMSMessage>
</xml>';
$xml = new SimpleXMLElement($string);
print_r('<pre>');
$Sid = (array)($xml->SMSMessage->Sid);
print_r($Sid[0]);
print_r($xml);
You can access Sid like so $Sid = (array)(xml->SMSMessage->Sid); echo $Sid[0];
But if you rather use array you can do this:
$string='<?xml version="1.0"?>
<xml>
<SMSMessage>
<Sid>xyz</Sid>
<DateUpdated>2013-05-02 18:43:19</DateUpdated>
</SMSMessage>
</xml>';
$array= json_decode(json_encode(new SimpleXMLElement($string)), true);
print_r('<pre>');
print_r($array['SMSMessage']['Sid']);
print_r($array);

Why does SimpleXML change my array to the array's first element when I use it?

Here is my code:
$string = <<<XML
<?xml version='1.0'?>
<test>
<testing>
<lol>hello</lol>
<lol>there</lol>
</testing>
</test>
XML;
$xml = simplexml_load_string($string);
echo "All of the XML:\n";
print_r $xml;
echo "\n\nJust the 'lol' array:";
print_r $xml->testing->lol;
Output:
All of the XML:
SimpleXMLElement Object
(
[testing] => SimpleXMLElement Object
(
[lol] => Array
(
[0] => hello
[1] => there
)
)
)
Just the 'lol' array:
SimpleXMLElement Object
(
[0] => hello
)
Why does it output only the [0] instead of the whole array? I dont get it.
What #Yottatron suggested is true, but not at all the cases as this example shows :
if your XML would be like this:
<?xml version='1.0'?>
<testing>
<lol>
<lolelem>Lol1</lolelem>
<lolelem>Lol2</lolelem>
<notlol>NotLol1</lolelem>
<notlol>NotLol1</lolelem>
</lol>
</testing>
Simplexml's output would be:
SimpleXMLElement Object
(
[lol] => SimpleXMLElement Object
(
[lolelem] => Array
(
[0] => Lol1
[1] => Lol2
)
[notlol] => Array
(
[0] => NotLol1
[1] => NotLol1
)
)
)
and by writing
$xml->lol->lolelem
you'd expect your result to be
Array
(
[0] => Lol1
[1] => Lol2
)
but instead of it, you would get :
SimpleXMLElement Object
(
[0] => Lol1
)
and by
$xml->lol->children()
you would get:
SimpleXMLElement Object
(
[lolelem] => Array
(
[0] => Lol1
[1] => Lol2
)
[notlol] => Array
(
[0] => NotLol1
[1] => NotLol1
)
)
What you need to do if you want only the lolelem's:
$xml->xpath("//lol/lolelem")
That gives this result (not as expected shape but contains the right elements)
Array
(
[0] => SimpleXMLElement Object
(
[0] => Lol1
)
[1] => SimpleXMLElement Object
(
[0] => Lol2
)
)
It's because you have two lol elements. In order to access the second you need to do this:
$xml->testing->lol[1];
this will give you "there"
$xml->testing->lol[0];
Will give you "hello"
The children() method of the SimpleXMLElement will give you an object containing all the children of an element for example:
$xml->testing->children();
will give you an object containing all the children of the "testing" SimpleXMLElement.
If you need to iterate, you can use the following code:
foreach($xml->testing->children() as $ele)
{
var_dump($ele);
}
There is more information about SimpleXMLElement here:
http://www.php.net/manual/en/class.simplexmlelement.php
what you might want to do is using the Json encode/decode
$jsonArray = Json_decode(Json_encode($xml), true);
With the true argument you can call instead of using -> use [name]
so an example would be:
$xml = file("someXmlFile.xml");
$jsonArray = Json_decode(Json_encode($xml), true);
foreach(jsonArray['title'] as $title){
Do something with $titles
}
if you have more than 1 element it will typical put in an #attributes if the elements has attributes. This can be countered by using: $title = $title['#attributes']
Hope it could help.
Ah yes, I remember simple XML nearly doing my head in with this parsing arrays issue
Try the below code. It will give you an array of LOL elements, or, if you've just got a single LOL element, it will return that in an array as well.
The main advantage of that is you can do something like foreach ($lol as $element) and it will still work on a single (or on 0) LOL element.
<?php
$string = <<<XML
<?xml version='1.0'?>
<test>
<testing>
<lol>hello</lol>
<lol>there</lol>
</testing>
</test>
XML;
$xml = simplexml_load_string($string);
echo "<pre>";
echo "All of the XML:\n";
print_r($xml);
echo "\n\nJust the 'lol' array:\n";
$test_lols = $xml->testing->children();
$childcount = count($test_lols);
if ($childcount < 2) {
$lol = array($test_lols->lol);
}
else {
$lol = (array) $test_lols;
$lol = $lol['lol'];
}
print_r($lol);
?>
Ran into this issue...
Xpath can be a little slow, so you can achieve the same effect with a simple for loop.
for ($i = 0; $i < count($xml->testing->lol); $i++) {
print_r($xml->testing->lol[$i]);
}

Categories