Simplexml: Working with Xml Containing Namespaces

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

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 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.

How to use namespaces when writing XML file with SimpleXML

Here is an example of how to do this using DOM:

<?php

$nsUrl = 'http://base.google.com/ns/1.0';

$doc = new DOMDocument('1.0', 'UTF-8');

$rootNode = $doc->appendChild($doc->createElement('rss'));
$rootNode->setAttribute('version', '2.0');
$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:g', $nsUrl);

$channelNode = $rootNode->appendChild($doc->createElement('channel'));
$channelNode->appendChild($doc->createElement('title', 'Removed'));
$channelNode->appendChild($doc->createElement('description', 'Removed'));
$channelNode->appendChild($doc->createElement('link', 'Removed'));

foreach ($products as $product) {
$itemNode = $channelNode->appendChild($doc->createElement('item'));
$itemNode->appendChild($doc->createElement('title'))->appendChild($doc->createTextNode($product['title']));
$itemNode->appendChild($doc->createElement('description'))->appendChild($doc->createTextNode($product['title']));
$itemNode->appendChild($doc->createElement('link'))->appendChild($doc->createTextNode($product['url']));
$itemNode->appendChild($doc->createElement('g:id'))->appendChild($doc->createTextNode($product['product_id']));
$itemNode->appendChild($doc->createElement('g:price'))->appendChild($doc->createTextNode($product['price_latest']));
$itemNode->appendChild($doc->createElement('g:brand'))->appendChild($doc->createTextNode($product['range']));
$itemNode->appendChild($doc->createElement('g:condition'))->appendChild($doc->createTextNode('new'));
$itemNode->appendChild($doc->createElement('g:image_link'))->appendChild($doc->createTextNode($product['image']));
}

echo $doc->saveXML();

See it working

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.

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.

XML - getting value from namespace using SimpleXML

The children() method doesn't return some kind of token for the namespace, it returns a list of elements - the children which are in the given namespace.

The $xml variable represents the top-level message element, which doesn't have any children in the http://www.blendlabs.com namespace, so $xml->children('http://www.blendlabs.com') will just return an empty list. You need to first navigate to the other element, and then get its children in the http://www.blendlabs.com namespace, which will include the loan element.

Since the top level element is in the http://www.mismo.org/residential/2009/schemas namespace, you might need an extra children() call to make sure you select that first.

You didn't provide a complete XML, so I can't test the code (I don't fancy manually writing all those close tags), but it will look something like this:

$marketing_value = (string)
$xml
->children('http://www.mismo.org/residential/2009/schemas')
->deal_sets->deal_set->deals->deal->loans->loan->extension->other
->children('http://www.blendlabs.com')
->loan->marketing_items->marketing_item->marketingvalue;


Related Topics



Leave a reply



Submit