How to echo information from xml in PHP - php

I have some problems with echo line from xml file.
How i can do it fine?
I try to
$test = file_get_contents('');
$test = iconv('WINDOWS-1251', 'UTF-8', $test);
$test = "<xmp>".$test."</xmp>";
And try to find with preg_match_all, but it isn't work.
preg_match_all('/<ya:created dc:date="\d+\-\d+\-\d+\T\d+\:\d+\:\d+/', $test, $output_array);
It's work on https://www.phpliveregex.com/ but isn't work on my site.
https://www.phpliveregex.com/p/qCH
My XML:
<?xml version="1.0" encoding="WINDOWS-1251"?>
<rdf:RDF
xml:lang="ru"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:ya="http://blogs.yandex.ru/schema/foaf/"
xmlns:img="http://blogs.yandex.ru/schema/foaf/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<foaf:Person>
<ya:publicAccess>allowed</ya:publicAccess>
<foaf:gender>male</foaf:gender>
<ya:created dc:date="2011-01-30T16:43:45+03:00"/>
<ya:lastLoggedIn dc:date="2019-01-16T18:54:55+03:00"/>
<ya:modified dc:date="2019-01-13T21:15:43+03:00"/>
</foaf:Person>
</rdf:RDF>

You would be better accessing it using something like SimpleXML and XPath. There are at least two ways of doing it, both here rely on using XPath but you have to use the namespaces (the ya: bit) to ensure you get the right element. As XPath returns a list of matches, I just use [0] to get the first one, if there are multiple ones you can use a loop...
$test = file_get_contents("data.xml");
$xml = simplexml_load_string($test);
// Version 1
// Fetch the ya:created element
$created = $xml->xpath("//ya:created")[0];
// Extract the attributes and print the date
echo $created[0]->attributes("http://purl.org/dc/elements/1.1/")->date;
// Version 2
// Extract the dd:date attribute (using the #)
$createdDate = $xml->xpath("//ya:created/#dc:date")[0];
echo $createdDate;
Forgot to say - if you want to use these fields for a database etc. you may need to cast them to a string to make sure they are converted...
$date = (string)$createdDate;

Related

Query XML File using PHP for Values

I am currently working on a project that requires me to query an XML file like php to return a value that matches the request. Take a look at the XML:
<ENVELOPE>
<MASTER>
<STKDETNAME>004-011</STKDETNAME>
<STKPNO>PTN771</STKPNO>
<STKPRICE></STKPRICE>
<STKOPBAL>500</STKOPBAL>
</MASTER>
<MASTER>
<STKDETNAME>004-012</STKDETNAME>
<STKPNO>PTN772</STKPNO>
<STKPRICE></STKPRICE>
<STKOPBAL>500</STKOPBAL>
</MASTER>
<MASTER>
<STKDETNAME>004-013</STKDETNAME>
<STKPNO>PTN773</STKPNO>
<STKPRICE></STKPRICE>
<STKOPBAL>1000</STKOPBAL>
</MASTER>
<MASTER>
<STKDETNAME>004-014</STKDETNAME>
<STKPNO>PTN774</STKPNO>
<STKPRICE></STKPRICE>
<STKOPBAL>1000</STKOPBAL>
</MASTER>
<MASTER>
<STKDETNAME>004-015</STKDETNAME>
<STKPNO>PTN775</STKPNO>
<STKPRICE>400</STKPRICE>
<STKOPBAL>1000</STKOPBAL>
</MASTER>
</ENVELOPE>
Now, I want to get the STKPRICE AND STKOPBAL for a SKTPNO= PTN773. This is what i have seen so far, but i don't know how to get the two values. I am new to XML.
$file = 'stocksum.xml';//same file as above
$xmlfile = simplexml_load_file($file);
$partno = PTN775;
$fnd = $xmlfile->xpath('/ENVELOPE/MASTER/STKPNO[.="$partno"]');
There are a couple of issues with the code which are just syntax problems, these are the partno needing quotes and when building the XPath expression, you use single quotes so it doesn't insert the actual part number.
BUT to get to your actual problem, if you change your XPath to the one used here, this will find the <MASTER> element whose <STKPNO> is the one your after. So then you can refer to the elements withing the <MASTER> element using standard SimpleXML object notation...
$partno = 'PTN775';
$fnd = $xmlfile->xpath('/ENVELOPE/MASTER[STKPNO="'.$partno.'"]');
echo $fnd[0]->STKPRICE.PHP_EOL;
Note that as xpath() returns a list of matches, I use $fnd[0] to get the first one.
Code which also has a check to see if the part actually exists...
$xmlfile = simplexml_load_file($file);
$partno = 'PTN7751';
$fnd = $xmlfile->xpath('/ENVELOPE/MASTER[STKPNO="'.$partno.'"]');
if ( count($fnd) == 0 ) {
echo "Not found";
}
else {
echo $fnd[0]->STKPRICE.PHP_EOL;
}

can't access xml node PHP

I have a page in php where I have to parse an xml.
I have done this for example:
$hotelNodes = $xml_data->getElementsByTagName('Hotel');
foreach($hotelNodes as $hotel){
$supplementsNodes2 = $hotel->getElementsByTagName('BoardBase');
foreach($supplementsNodes2 as $suppl2) {
echo'<p>HERE</p>'; //not enter here
}
}
}
In this code I access to each hotel of my xml, and foreach hotel I would like to search the tag BoardBase but it doesn0t enter inside it.
This is my xml (cutted of many parts!!!!!)
<hotel desc="DESC" name="Hotel">
<selctedsupplements>
<boardbases>
<boardbase bbpublishprice="0" bbprice="0" bbname="Colazione Continentale" bbid="1"></boardbase>
</boardbases>
</selctedsupplements>
</occupancy></occupancies>
</hotel>
I have many nodes that doesn't have BoardBase but sometimes there is but not enter.
Is possible that this node isn't accessible?
This xml is received by a server with a SoapClient.
If I inspect the XML printed in firebug I can see the node with opacity like this:
I have also tried this:
$supplementsNodes2 = $hotel->getElementsByTagName('boardbase');
but without success
2 issues I can see from the get-go: XML names are case-sensitive, hence:
$hotelNodes = $xml_data->getElementsByTagName('Hotel');
Can't work, because your xml node looks like:
<hotel desc="DESC" name="Hotel">
hotel => lower-case!
As you can see here:
[...] names for such things as elements, while XML is explicitly case sensitive.
The official specs specify tag names as case-sensitive, so getElementsByTagName('FOO') won't return the same elements as getElementsByTagName('foo')...
Secondly, you seem to have some tag-soup going on:
</occupancy></occupancies>
<!-- tag names don't match, both are closing tags -->
This is just plain invalid markup, it should read either:
<occupancy></occupancy>
or
<occupancies></occupancies>
That would be the first 2 ports of call.
I've set up a quick codepad using this code, which you can see here:
$xml = '<hotel desc="DESC" name="Hotel">
<selctedsupplements>
<boardbases>
<boardbase bbpublishprice="0" bbprice="0" bbname="Colazione Continentale" bbid="1"></boardbase>
</boardbases>
</selctedsupplements>
<occupancy></occupancy>
</hotel>';
$dom = new DOMDocument;
$dom->loadXML($xml);
$badList = $dom->getElementsByTagName('Hotel');
$correctList = $dom->getElementsByTagName('hotel');
echo sprintf("%d",$badList->lenght),
' compared to ',
$correctList->length, PHP_EOL;
The output was "0 compared to 1", meaning that using a lower-case selector returned 1 element, the one with the upper-case H returned an empty list.
To get to the boardbase tags for each hotel tag, you just have to write this:
$hotels = $dom->getElementsByTagName('html');
foreach($hotels as $hotel)
{
$supplementsNodes2 = $hotel->getElementsByTagName('boardbase');
foreach($supplementsNodes2 as $node)
{
var_dump($node);//you _will_ get here now
}
}
As you can see on this updated codepad.
Alessandro, your XML is a mess (=un casino), you really need to get that straight. Elias' answer pointed out some very basic stuff to consider.
I built on the code pad Elias has been setting up, it is working perfectly with me:
$dom = new DOMDocument;
$dom->loadXML($xml);
$hotels = $dom->getElementsByTagName('hotel');
foreach ($hotels as $hotel) {
$bbs = $hotel->getElementsByTagName('boardbase');
foreach ($bbs as $bb) echo $bb->getAttribute('bbname');
}
see http://codepad.org/I6oxkEOC

How to convert XML attributes to text nodes

I have a PHP script that pulls an XML file from a remote server, and converts it to JSON using simplexml_load_string and json_encode. However, the simplexml_load_string seems to ignore inline attributes, like so:
<AxisFeedrate dataItemId="iid7" timestamp="2012-03-21T15:15:41-04:00" sequence="7" name="Yfrt" subType="ACTUAL" units="MILLIMETER/SECOND">UNAVAILABLE</AxisFeedrate>
In this case the JSON representation would be {AxisFeedrate: 'UNAVAILABLE'}
However, I need to have those attributes available. One idea I've been approaching is replacing strings to turn the attributes into text nodes like so:
<AxisFeedrate>
<dataItemId>iid7</dataItemId>
<timestamp>2012-03-21T15:15:41-04:00</timestamp>
<sequence>7</sequence>
<name>Yfrt</name>
<subType>ACTUAL</subType>
<units>MILLIMETER/SECOND"</units>
<value>UNAVAILABLE</value>
</AxisFeedrate>
I can turn the attributes into their own tag elements with regular find/replace, but I'm having trouble wrapping the original text value in a Value tag, at least with find/replace.
What are some good approaches for doing this? The above chunk of XML is in the middle of many similar chunks on different data items, so I couldn't just start by replacing the first closing > with >...
You could use SimpleXML itself to read the attributes.
Example:
<?php
$xml=simplexml_load_string('<AxisFeedrate dataItemId="iid7" timestamp="2012-03-21T15:15:41-04:00" sequence="7" name="Yfrt" subType="ACTUAL" units="MILLIMETER/SECOND">UNAVAILABLE</AxisFeedrate>');
foreach($xml->attributes() as $k=>$v) {
echo $k." -> ".(string)$v."\n";
}
?>
Output:
dataItemId -> iid7
timestamp -> 2012-03-21T15:15:41-04:00
sequence -> 7
name -> Yfrt
subType -> ACTUAL
units -> MILLIMETER/SECOND
Try this regex: ([\w]*?)="(.*?)" with this replace <$1>$2</$1>\n
You should use SimpleXML. Be aware though, that you have to cast values to string type explicitly, or you'll get objects.
$xml_string = <<<XML
<AxisFeedrate
dataItemId="iid7"
timestamp="2012-03-21T15:15:41-04:00"
sequence="7"
name="Yfrt"
subType="ACTUAL"
units="MILLIMETER/SECOND"
>UNAVAILABLE</AxisFeedrate>
XML;
$xml = simplexml_load_string($xml_string);
$axis_info = array('value' => (string)$xml);
foreach($xml -> attributes() as $attr => $val) {
$axis_info[$attr] = (string) $val;
}
echo json_encode(array("AxisFeedrate" => $axis_info));
Update:
This will give you a more generic version, but notice that the attributes are cast as an array and that this only works on a single element:
$xml_string = <<<XML
<AxisFeedrate dataItemId="iid7" timestamp="2012-03-21T15:15:41-04:00" sequence="7" name="Yfrt" subType="ACTUAL" units="MILLIMETER/SECOND">UNAVAILABLE</AxisFeedrate>
XML;
$xml = simplexml_load_string($xml_string);
$obj_name = $xml -> getName();
$attributes = (array) $xml->attributes();
$axis_info[$obj_name] = $attributes["#attributes"];
$axis_info[$obj_name]['value'] = (string) $xml;
echo json_encode($axis_info);

creating multiple xml nodes with same namespaces in php

I have the following code
$dom = new DOMDocument('1.0', 'utf-8');
$headerNS = $dom->createElementNS('http://somenamespace', 'ttauth:authHeader');
$accesuser = $dom->createElementNS('http://somenamespace', 'ttauth:Accessuser','aassdd');
$accesscode = $dom->createElementNS('http://somenamespace', 'ttauth:Accesscode','aassdd');
$headerNS->appendChild($accesuser);
$headerNS->appendChild($accesscode);
echo "<pre>";
echo ($dom->saveXML($headerNS));
echo "</pre>";
IT will produce the following xml as output
<?xml version="1.0" ?>
<ttauth:authHeader xmlns:ttauth="http://somenamespace">
<ttauth:Accessuser>
ApiUserFor136
</ttauth:Accessuser>
<ttauth:Accesscode>
test1234
</ttauth:Accesscode>
</ttauth:authHeader>
But I want the following output
<ttauth:authHeader xmlns:ttauth="http://somenamespace">
<ttauth:Accessuser xmlns:ttauth="http://somenamespace">
aassdd
</ttauth:Accessuser>
<ttauth:Accesscode xmlns:ttauth="somenamespace">
aassdd
</ttauth:Accesscode>
</ttauth:authHeader>
See the xmlns is not included in elements other than root element but I want xmlns to be included in all elements Is there anything I am doing wrong ??
Probably the PHP parser does not add renaming of the same namespace "http://somenamespace" with the same prefix "ttauth" because it is redundant. Both xmls you shown ( the output and expected ) are equivalent. If you want to be sure you have the namespaces attributes as you want, you should add them manually by using addAtribute - http://www.php.net/manual/en/domdocument.createattribute.php. See the following code snippet:
$domAttribute = $domDocument->createAttribute('xmlns:ttauth');
$domAttribute->value = 'http://somenamespace';
$accessuser->appendChild($domAttribute);
Hope it helps
instead of using
$accesuser = $dom->createElementNS('http://somenamespace', 'ttauth:Accessuser','aassdd');
I used
$accesuser = $dom->createElement('http://somenamespace', 'ttauth:Accessuser','aassdd');
and then
$accesuser->setAttribute('xmlns:ttauth', ('http://somenamespace');
it works fine for any number of nodes

Parsing xml-like data

I have a string with xml-like data:
<header>Article header</header>
<description>This article is about you</description>
<text>some <b>html</b> text</text>
I need to parse it into variables/object/array "header", "description", "text".
What is the best way to do this? I tried $vars = simplexml_load_string($content), but it does not work, because it is not 100% pure xml (no <?xml...).
So, should I use preg_match? Is it the only way?
Your XML string looks like (though may or may not be) an XML document fragment. PHP can work with this using the DOMDocumentFragment class.
$doc = new DOMDocument;
$frag = $doc->createDocumentFragment();
$frag->appendXML($content);
$parsed = array();
foreach ($frag->childNodes as $element) {
if ($element->nodeType === XML_ELEMENT_NODE) {
$parsed[$element->nodeName] = $element->textContent;
}
}
echo $parsed['description']; // This article is about you
With a string like that, simlexml_load_string should work.
Because of the 3rd tag, if you try to get that it will fail, and not return the correct value (because there is a sub part within the tag.
Try something like this, which might work for you:
$xml = simplexml_load_string($content)
$text = $xml->text->asXML();
You should also take a look at this documentation: http://www.php.net/manual/en/simplexmlelement.asxml.php. They also do the same thing with the string. You might wanna use this option instead of simplexml_load_string too
$xml = new SimpleXMLElement($string);

Categories