How do I parse XML containing custom namespaces using SimpleXML?
the usage of ccc:fid is an extension of the namespace which needs to be declared in xml in order to be able to use it in libraries like simplexml.
Here are some examples of descriptions of usin a namespace:
- http://www.w3.org/TR/1999/REC-xml-names-19990114/
- http://www.w3.org/TR/xml-names/
Hope that helps, albeit it is a little complicated.
Parse XML namespaces with php SimpleXML
I have given same type of answer here - solution to your question
You just need to register Namespace and then you can work normally with simplexml_load_file and XPath
<?php
$data = "http://alerts.weather.gov/cap/tx.php?x=1";
$entries = file_get_contents($data);
$entries = new SimpleXmlElement($entries);
if(count($entries)):
//echo "<pre>";print_r($entries);die;
//alternate way other than registring NameSpace
//$asin = $asins->xpath("//*[local-name() = 'ASIN']");
$entries->registerXPathNamespace('prefix', 'http://www.w3.org/2005/Atom');
$result = $entries->xpath("//prefix:entry");
//echo count($asin);
//echo "<pre>";print_r($result);die;
foreach ($result as $entry):
//echo "<pre>";print_r($entry);die;
$dc = $entry->children('urn:oasis:names:tc:emergency:cap:1.1');
echo $dc->event."<br/>";
echo $dc->effective."<br/>";
echo "<hr>";
endforeach;
endif;
That's it.
How to easily parse XML documents with namespaces in PHP using SimpleXML?
Got my answer from the code provided by IMSoP. The PHP snippet I ended up using was adapted from aforementioned link, using XML similar to that of the OP:
foreach ($xml->children(NS_ATOM)->entry as $entry) {
echo "<item>".PHP_EOL;
echo "<title>".$entry->title."</title>".PHP_EOL;
echo "<link>".$entry->link->attributes(null)->href."</link>".PHP_EOL;
echo "<image>".$entry->children(NS_MEDIA)->group->children(NS_MEDIA)->thumbnail->attributes(null)->url."</image>".PHP_EOL;
echo "<description>".$entry->children(NS_MEDIA)->group->children(NS_MEDIA)->description."</description>".PHP_EOL;
echo "<guid>".$entry->children(NS_YT)->videoId."</guid>".PHP_EOL;
echo "<views>".$entry->children(NS_MEDIA)->group->children(NS_MEDIA)->community->children(NS_MEDIA)->statistics->attributes(null)->views."</views>".PHP_EOL;
echo "<pubDate>".$entry->published."</pubDate>".PHP_EOL;
echo "</item>".PHP_EOL;
}
Hope this can help somebody in the future. It was the easiest example of XML namespace parsing I've come across so far.
Parse xml with namespaces with SimpleXMLparser php
You should not read the namespaces from the document. The namespace is a unique string defining the XML semantic the tag is part of. Your XML is a good example for that, because it has Point
elements in two different namespaces.
p:Point
is {http://example.org}:Pointgml:Point
is {http://www.opengis.net/gml}:Point
The namespace prefixes like p
and gml
are aliases to make a document smaller and more readable. They are only valid for the element and its children. They can be redefined at any point. More important they are only valid for the document.
So to read XML you define own prefixes for the namespaces and use them with Xpath or you use the namespace aware variants of the DOM methods like getAttributeNS()
. Xpath is by a long way the more elegant solution. You can use the prefixes from the document or different ones.
$element = simplexml_load_string($content);
$element->registerXPathNamespace('gml', 'http://www.opengis.net/gml');
$element->registerXPathNamespace('p', 'http://example.org');
$result = [];
$positions = $element->xpath('//p:Point[1]//gml:pos');
foreach ($positions as $pos) {
$result[] = (string)$pos;
}
var_dump($result);
Output: https://eval.in/159739
array(5) {
[0]=>
string(23) "-3.84307585 43.46031547"
[1]=>
string(23) "-3.84299411 43.46018513"
[2]=>
string(23) "-3.84299935 43.45998723"
[3]=>
string(23) "-3.84309913 43.46054546"
[4]=>
string(23) "-3.84307585 43.46031547"
}
parse an XML with SimpleXML which has multiple namespaces
I think you need to register the namespacing and access with XPath. Something like the following should get you going (I haven't the facility to test this).
$xml = simplexml_load_string($res, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/");
$xml->registerXPathNamespace('soap-env', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('eb', 'http://www.ebxml.org/namespaces/messageHeader');
$xml->registerXPathNamespace('wsse', 'http://schemas.xmlsoap.org/ws/2002/12/secext');
Then you can do something like:
foreach($xml->xpath('//eb:MessageHeader') as $header)
{
var_export($header->xpath('//eb:CPAId')); // Should output 'something'.
}
You may not need to register the namespacing, thinking about it, as they are alredy present in the XML. Not sure on this though, would need to test.
Hope this helps.
SimpleXML: Working with XML containing namespaces
You could work with XPath and registerXPathNamespace()
:
$xml->registerXPathNamespace("georss", "http://www.georss.org/georss");
$xml->registerXPathNamespace("gml", "http://www.opengis.net/gml");
$pos = $xml->xpath("/georss:where/gml:Point/gml:pos");
From the docs, emphasis mine:
registerXPathNamespace […] Creates a prefix/ns context for the next XPath query.
More ways to handle namespaces in SimpleXML can be found here, for example:
Stuart Herbert On PHP - Using SimpleXML To Parse RSS Feeds
Parsing XML with nested namespaces using simpleXML?
Xpath would probably be the easiest:
// load the xml into the object
$xml = simplexml_load_file('word/document.xml');
//Use that namespace
$namespaces = $xml->getNameSpaces(true);
$xml->registerXPathNamespace('w', $namespaces['w']);
$nodes = $xml->xpath('/w:document/w:body//w:t');
foreach($nodes as $node) {
echo (string) $node . "\n\n";
}
access php simplexml with namespaces
You have nested elements that are in different XML namespaces. In concrete you have got two additional namespaces involved:
$nsUriOaiDc = 'http://www.openarchives.org/OAI/2.0/oai_dc/';
$nsUriDc = 'http://purl.org/dc/elements/1.1/';
The first one is for the <oai_dc:dc>
element which contains the second ones * <dc:*>
* elements like <dc:description>
and so on. Those are the elements you're looking for.
In your code you already have a good nose how this works:
$data = $record->children( 'http://www.openarchives.org/OAI/2.0/oai_dc/' );
$rows = $data->children( 'http://purl.org/dc/elements/1.1/' );
However there is a little mistake: the $data
children are not children of $record
but of $record->metadata
.
You also do not need to nest two foreach
into each other. The code example:
$nsUriOaiDc = 'http://www.openarchives.org/OAI/2.0/oai_dc/';
$nsUriDc = 'http://purl.org/dc/elements/1.1/';
$records = $xml->ListRecords->record;
foreach ($records as $record)
{
$data = $record->metadata->children($nsUriOaiDc);
$rows = $data->children($nsUriDc);
echo $rows->date;
break;
}
/** output: 1921 **/
If you are running into problems like these, you can make use of $record->asXML('php://output');
to show which element(s) you are currently traversing to.
Related Topics
Parse Select Clause of SQL Queries into a PHP Array
Getting the Difference Between Two Time/Dates Using PHP
MySQL & PHP Parameter 1 as Resource
Check If Value Exists Before Inserting into MySQL Db in a PHP Script
Adding 1 Day to a Datetime Format Value
Laravel Check If Collection Is Empty
Is There a PHP Function for Swapping the Values of Two Variables
Sending Post Parameters with Postman Doesn't Work, But Sending Get Parameters Does
Regular Expression Preg_Quote Symbols Are Not Detected
PHP Get Name of Current Directory
How to See the Extensions Loaded by PHP
Empty String Comparison to Zero Gives Different Result in PHP 8 Than in Previous Versions
Fatal Error: Call to Undefined Method MySQLi_Stmt::Get_Result()