Getting a specific XML element value with PHP - php

I have an XML structure like this
<companies>
<company>
<vatno>12345678</vatno>
<name>
<founded>2013-12-31</founded>
<text>XYZ Inc</text>
</name>
<location>
<streetname>West Road</streetname>
<county>
<no>12345</no>
<text>East County</text>
<county>
</location>
</company>
</companies>
I am trying to get specific info from the elements into PHP variables.
To get "vatno" I use:
$vatno = $xmlObject->item($i)->getElementsByTagName('vatno')->item(0)->childNodes->item(0)->nodeValue;
But what if I need the county name for example?
I cannot use getElementsByTagName('text') as it would get the company name also using the element name "text".

You may be better off using SimpleXML, you can then access the various components in a more intuitive way.
The example above would be something like...
$data = <<< XML
<companies>
<company>
<vatno>12345678</vatno>
<name>
<founded>2013-12-31</founded>
<text>XYZ Inc</text>
</name>
<location>
<streetname>West Road</streetname>
<county>
<no>12345</no>
<text>East County</text>
</county>
</location>
</company>
</companies>
XML;
$xml = simplexml_load_string($data);
foreach ( $xml->company as $company ) {
echo $company->vatno.PHP_EOL;
echo $company->location->county->text.PHP_EOL;
}
So each sub element is accessed using ->.
If you wanted to stick with what you already had, you should be able to use...
$countyName = $xmlObject->item($i)->getElementsByTagName('text')->item(1)
->nodeValue;
Using item(1) will fetch the second instance of the <text> elements, so this assumes that the name will have this value as well.

It works with SimpleXML if I use
$xml = simplexml_load_string($data);
foreach ( $xml->companies->company as $company ) {
echo $company->vatno.PHP_EOL;
echo $company->location->county->text.PHP_EOL;
}

Related

XMLsimple get value of next element

This is a small part of the XML file I am reading:
<hotel>
<Location>
<Identifier>D5023</Identifier>
<IsAvailable>true</IsAvailable>
<Availability>
<TimeStamp>2015-06-11T16:04:23.887</TimeStamp>
<Rooms>525</Rooms>
<Beds>845</Beds>
</Availability>
</Location>
<Location>
ect.
</Location>
</hotel>
Using XMLsimple I want to get the number of available rooms for location D5023 (and other locations). But because the Identifier is a child from the Location attribute I am struggling to get the right data.
This is what I came up with, but obviously this doesnt work
$hotel->Location->Identifier['D5023']->Availability->Rooms;
How can I get this right?
You can use SimpleXMLElement::xpath() to get specific part of XML by complex criteria, for example :
$xml = <<<XML
<hotel>
<Location>
<Identifier>D5023</Identifier>
<IsAvailable>true</IsAvailable>
<Availability>
<TimeStamp>2015-06-11T16:04:23.887</TimeStamp>
<Rooms>525</Rooms>
<Beds>845</Beds>
</Availability>
</Location>
<Location>
ect.
</Location>
</hotel>
XML;
$hotel = new SimpleXMLElement($xml);
$result = $hotel->xpath("/hotel/Location[Identifier='D5023']/Availability/Rooms")[0];
echo $result;
output :
525
Demo
there are more Location so you have too loop on :
foreach ($hotel->Location as $l) {
if ("D5023" === $l->Identifier) {
var_dump($l->Availability->Rooms);
}
}
you load your file and loop through the XML file and check the ID , don't forget to cast the xml from object to string so you can compare 2 strings to each other and not an object to a string.
if( $xml = simplexml_load_file("path_to_xml.xml",'SimpleXMLElement', LIBXML_NOWARNING) )
{
echo("File loaded ...");
// loop through XML
foreach ($xml->hotel as $hotel)
{
// convert the xml object to a string and compare it with the room ID
if((string)$hotel->Location->Identifier == "D5023")
{
echo("there are ".$hotel->Location->Availability->Rooms."Available room in this hotel");
}
}
}
else
echo("error loading file!");
hope that helps !

Trouble figuring out how parsed xml is stored - simpleXML

Let's say my XML is like this:
<?xml version="1.0"?>
<lists>
<list
path=".">
<entry
kind="dir">
<name>Assignment1.1</name>
<commit
revision="1668">
<author>netid</author>
<date>2011-09-07T03:03:58.367692Z</date>
</commit>
</entry>
<entry
kind="file">
<name>Assignment1.1/.classpath</name>
<size>397</size>
<commit
revision="1558">
<author>netid</author>
<date>2011-09-06T17:00:52.998920Z</date>
</commit>
.
.
.
</list>
</lists>
And I store it in a SimpleXML object using
$xml_list = simplexml_load_file(dirname(__FILE__).'/svn_list.xml');
How would I access for example, the revision variable containing 1558?
I can't seem to figure it out using a combination of echo and print_r.
SimpleXML uses a set of classes which implement iterators to work through them, so you can loop through each node using foreach, however the easiest way to navigate the XML once it's loaded is by using SimpleXMLElement::xPath(). To get revision 1558, you can make the following call:
$commit = $xml_list->xpath('//list/entry/commit[#revision="1558"]');
This will return you the nodes underneath <commit revision="1558">, and you can then access them from the $commit variable, which extends ArrayObject.
To get the actual content of the <author> element, you must do the following:
print((string)$commit[0]->author);
SimpleXMLElement instances need to be cast to a type to expose their actual values.
Also, if you want to dump the content of $commit to see its child nodes, the easiest way is to call the asXml() method as follows:
print($commit[0]->asXml());
You are facing difficulties because you have error on your XML file , The </entry> tag was not closed.
You could traverse like this.
<?php
$xml='<lists>
<list>
<entry
kind="dir">
<name>Assignment1.1</name>
<commit
revision="1668">
<author>netid</author>
<date>2011-09-07T03:03:58.367692Z</date>
</commit>
</entry>
<entry
kind="file">
<name>Assignment1.1/.classpath</name>
<size>397</size>
<commit
revision="1558">
<author>netid</author>
<date>2011-09-06T17:00:52.998920Z</date>
</commit>
</entry>
</list>
</lists>';
$xml = simplexml_load_string($xml);
foreach ($xml->list->entry[0]->commit->attributes() as $a=>$v)
{
echo $v;
}
OUTPUT :
1668

Show all items that Match in XML using PHP

This is my XML file named: full.xml
I need your help. I need a PHP script that open "full.xml"
and only display all values of the nodes that have .email
Example of the Output I want:
sales#company1.com
sales#company2.com
sales#company3.com
Thanks! I will thank you so much!
EDIT
$Connect = simplexml_load_file("full.xml");
return $Connect->table[0]->*.email;
The design of your XML is not very smart. With this xpath expression, you select all nodes with .email at the end of their name:
$xml = simplexml_load_string($x); // assume XML in $x
$results = $xml->xpath("//*[substring(name(),string-length(name())-" . (strlen('.email') - 1) . ") = '.email']");
--> result is an array with the selected nodes.
BTW: if you have any chance of CHANGING the structure of the XML, AVOID combining information within node names like <company1.email>, but do it like this:
...
<companies>
<company id="1">
<email>info#company1.com</email>
<tel>+498988123456</tel>
<name>somename</name>
</company>
<company id="2">
<email>info#company2.com</email>
<tel>+498988123457</tel>
<name>someothername</name>
</company>
</companies>
....
It will be much easier to read and parse.

simplexml, returning multiple items with the same tag

I have the following XML file loaded into php simplexml.
<adf>
<prospect>
<customer>
<name part="first">Bob</name>
<name part="last">Smith</name>
</customer>
</prospect>
</adf>
using
$customers = new SimpleXMLElement($xmlstring);
This will return "Bob" but how do I return the last name?
echo $customers->prospect[0]->customer->contact->name;
You can access the different <name> elements by number, using array-style syntax.
$names = $customers->prospect[0]->customer->name;
echo $names[0]; // Bob
echo $names[1]; // Smith
In fact, you're already doing it for the <prospect> element!
See also Basic SimpleXML Usage in the manual.
If you want to select elements based on some criteria, then XPath is the tool to use.
$customer = $customers->prospect[0]->customer;
$last_names = $customer->xpath('name[#part="last"]'); // always returns an array
echo $last_names[0]; // Smith

Parse XML in PHP by specific attribute

I need to get <name> and <URL> tag's value where subtype="mytype".How can do it in PHP?
I want document name and test.pdf path in my result.
<?xml version="1.0" encoding="UTF-8"?>
<test>
<required>
<item type="binary">
<name>The name</name>
<url visibility="restricted">c:/temp/test/widget.exe</url>
</item>
<item type="document" subtype="mytype">
<name>document name</name>
<url visiblity="visible">c:/temp/test.pdf</url>
</item>
</required>
</test>
Use SimpleXML and XPath, eg
$xml = simplexml_load_file('path/to/file.xml');
$items = $xml->xpath('//item[#subtype="mytype"]');
foreach ($items as $item) {
$name = (string) $item->name;
$url = (string) $item->url;
}
PHP 5.1.2+ has an extension called SimpleXML enabled by default. It's very useful for parsing well-formed XML like your example above.
First, create a SimpleXMLElement instance, passing the XML to its constructor. SimpleXML will parse the XML for you. (This is where I feel the elegance of SimpleXML lies - SimpleXMLElement is the entire library's sole class.)
$xml = new SimpleXMLElement($yourXml);
Now, you can easily traverse the XML as if it were any PHP object. Attributes are accessible as array values. Since you're looking for tags with specific attribute values, we can write a simple loop to go through the XML:
<?php
$yourXml = <<<END
<?xml version="1.0" encoding="UTF-8"?>
<test>
<required>
<item type="binary">
<name>The name</name>
<url visibility="restricted">c:/temp/test/widget.exe</url>
</item>
<item type="document" subtype="mytype">
<name>document name</name>
<url visiblity="visible">c:/temp/test.pdf</url>
</item>
</required>
</test>
END;
// Create the SimpleXMLElement
$xml = new SimpleXMLElement($yourXml);
// Store an array of results, matching names to URLs.
$results = array();
// Loop through all of the tests
foreach ($xml->required[0]->item as $item) {
if ( ! isset($item['subtype']) || $item['subtype'] != 'mytype') {
// Skip this one.
continue;
}
// Cast, because all of the stuff in the SimpleXMLElement is a SimpleXMLElement.
$results[(string)$item->name] = (string)$item->url;
}
print_r($results);
Tested to be correct in codepad.
Hope this helps!
You can use the XML Parser or SimpleXML.

Categories