I really need help with using namespaces. How do I get the following code to work properly?
<?php
$mytv = simplexml_load_string(
'<?xml version="1.0" encoding="utf-8"?>
<mytv>
<mytv:channelone>
<mytv:description>comedy that makes you laugh</mytv:description>
</mytv:channelone>
</mytv>'
);
foreach ($mytv as $mytv1)
{
echo 'description: ', $mytv1->children('mytv', true)->channelone->description;
}
?>
All I'm trying to do is get the content inside the name element.
when ever yu are using the namespaces in xml yu should define the namespaces what ever you use..! in the code what i posted you can see how you can define the namespace you are using..
you need to display the description specific to the namespace isn't it..? correct me if I'm wrong., and please post yur purpose properly so that i can understand your problem..
Use this code and see if you can get some idea..
$xml ='<mytv>
<mytv:channelone xmlns:mytv="http://mycompany/namespaces/mytvs">
<mytv:description >comedy that makes you laugh</mytv:description>
</mytv:channelone>
</mytv>';
$xml = simplexml_load_string($xml);
$doc = new DOMDocument();
$str = $xml->asXML();
$doc->loadXML($str);
$bar_count = $doc->getElementsByTagName("description");
foreach ($bar_count as $node)
{
echo $node->nodeName." - ".$node->nodeValue."-".$node->prefix. "<br>";
}
here., the value, "$node->prefix" will be the namespace of the tag containing "description".
getElementsByTagName("description") is used to get all the elements in the xml containing description as tags...!! and then later using the "$node->prefix" you compare with the specific namespace as required for you and then print..
Related
Given the following xml:
<data xmlns:ns2="...">
<versions>
<ns2:version type="HW">E</ns2:version>
<ns2:version type="FW">3160</ns2:version>
<ns2:version type="SW">3.4.1 (777)</ns2:version>
</versions>
...
</data>
I am trying to parse the third attribute ~ns2:version type="SW" but when running the following code I get nothing..
$s = simplexml_load_file('data.xml');
echo $s->versions[2]->{'ns2:version'};
Running this gives the following output:
$s = simplexml_load_file('data.xml');
var_dump($s->versions);
How can I properly get that attribute?
You've got some quite annoying XML to work with there, at least as far as SimpleXML is concerned.
Your version elements are in the ns2 namespace, so in order to loop over them, you need to do something like this:
$s = simplexml_load_string($xml);
foreach ($s->versions[0]->children('ns2', true)->version as $child) {
...
}
The children() method returns all children of the current tag, but only in the default namespace. If you want to access elements in other namespaces, you can pass the local alias and the second argument true.
The more complicated part is that the type attributes is not considered to be part of this same namespace. This means you can't use the standard $element['attribute'] form to access it, since your element and attribute are in different namespaces.
Fortunately, SimpleXML's attributes() method works in the same way as children(), and so to access the attributes in the global namespace, you can pass it an empty string:
$element->attributes('')->type
In full, this is:
$s = simplexml_load_string($xml);
foreach ($s->versions[0]->children('ns2', true)->version as $child) {
echo (string) $child->attributes()->type, PHP_EOL;
}
This will get you the output
HW
FW
SW
To get the third attribute.
$s = simplexml_load_file('data.xml');
$sxe = new SimpleXMLElement($s);
foreach ($sxe as $out_ns) {
$ns = $out_ns->getNamespaces(true);
$child = $out_ns->children($ns['ns2']);
}
echo $child[2];
Out put:
3.4.1 (777)
I am trying to write a code where it will find a specific element in my XML file and then change the value of the text node. The XML file has different namespaces. Till now, I have managed to register the namespaces and also echo the text node of the element, which I want to change.
<?php
$xml = simplexml_load_file('getobs.xml');
$xml->registerXPathNamespace('g','http://www.opengis.net/gml');
$result = $xml->xpath('//g:beginPosition');
foreach ($result as $title) {
echo $title . "\n";
}
?>
My question is: How can I change the value of this element using SimpleXML? I tried to use the nodeValue command but I am not able to make it work.
This is a part of the XML:
<sos:GetObservation xmlns:sos="http://www.opengis.net/sos/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" service="SOS" version="1.0.0" srsName="urn:ogc:def:crs:EPSG:4326">
<sos:offering>urn:gfz:cawa:def:offering:meteorology</sos:offering>
<sos:eventTime>
<ogc:TM_During xmlns:ogc="http://www.opengis.net/ogc" xsi:type="ogc:BinaryTemporalOpType">
<ogc:PropertyName>urn:ogc:data:time:iso8601</ogc:PropertyName>
<gml:TimePeriod xmlns:gml="http://www.opengis.net/gml">
<gml:beginPosition>2011-02-10T01:10:00.000</gml:beginPosition>
Thanks
Dimitris
In the end I managed to do it by using the PHP XML DOM.
Here is the code that I used in order to change the text node of a specific element:
<?php
// create new DOM document and load the data
$dom = new DOMDocument;
$dom->load('getobs.xml');
//var_dump($dom);
// Create new xpath and register the namespace
$xpath = new DOMXPath($dom);
$xpath->registerNamespace('g','http://www.opengis.net/gml');
// query the result amd change the value to the new date
$result = $xpath->query("//g:beginPosition");
$result->item(0)->nodeValue = 'sds';
// save the values in a new xml
file_put_contents('test.xml',$dom->saveXML());
?>
Not wanting to switch from the code I've already made for SimpleXML, I found this solution:
http://www.dotdragnet.com/forum/index.php?topic=3979.0
Specificially:
$numvotes = $xml->xpath('/gallery/image[path="'.$_GET["image"].'"]/numvotes');
...
$numvotes[0][0] = $votes;
Hope this helps!
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
Using my below code i can read <abcxyz> xml tag easily. but how can i read the data between <abc:xyz> </abc:xml> xml tag..
xml tag using php.pls help....
my php sample code...
$objDOM->load("abc.xml");
$note = $objDOM->getElementsByTagName("note");
foreach( $note as $value )
{
$tasks = $value->getElementsByTagName("tasks");
$task = $tasks->item(0)->nodeValue;
$details = $value->getElementsByTagName("details");
$detail = $details->item(0)->nodeValue;
echo "$task :: $detail<br>";
}
My XML sample code:
<mynotes>
<note>
<tasks>Task 1</tasks>
<details>Detail 1</details>
</note>
<abc:xyz> Cannot Read the XML data between this tag</abc:xyz>
</mynotes>
Pls guide me...
Thanks
Riad
abc:xyz means that the element is named xyz, and the namespace is indicated by abc. The namespace part is actually shorthand for an URI, which is usually also given in the XML file. For example, you may see this:
xmlns:abc="http://www.abc.com/xml"
In this case, elements which have abc before the colon are in the namespace http://www.abc.com/xml.
To retrieve this element, you need to use getElementsByTagNameNS and pass http://www.abc.com/xml as the namespace.
you need DOMDocument::getElementsByTagNameNS
Going with the DOMDocument::getElementsByTagNameNS way like others have suggested, here is a working code (including reading the inner content), assuming that you also have some namespace declaration (like <abc:response xmlns:abc="http://api-url"> ) part as pointed out by #Sjoerd -
$xml = '<?xml version="1.0"?>
<abc:response xmlns:abc="http://api-url">
<mynotes>
<note>
<tasks>Task 1</tasks>
<details>Detail 1</details>
</note>
<abc:xyz> Can Read the XML data between this tag!!</abc:xyz>
</mynotes>
</abc:response>';
$dom = new DOMDocument;
// load the XML string defined above
$dom->loadXML($xml);
foreach ($dom->getElementsByTagNameNS('http://api-url', '*') as $element)
{
//echo 'see - local name: ', $element->localName, ', prefix: ', $element->prefix, "\n";
if($element->localName == "xyz")
echo get_inner_html($element);
}
function get_inner_html( $node )
{
$innerHTML= '';
$children = $node->childNodes;
foreach ($children as $child)
{
$innerHTML .= $child->ownerDocument->saveXML( $child );
}
return $innerHTML;
}
Here is a working link showing the output.
Note that I have just wrapped your xml inside this -
'<?xml version="1.0"?>
<abc:response xmlns:abc="http://api-url">'
.$yourxml
.'</abc:response>';
I used the solution I got from here PHP DOM get nodevalue html? (without stripping tags)... was stuck with a similar problem these days.
I have an XML document that looks like this:
<Data
xmlns="http://www.domain.com/schema/data"
xmlns:dmd="http://www.domain.com/schema/data-metadata"
>
<Something>...</Something>
</Data>
I am parsing the information using SimpleXML in PHP. I am dealing with arrays and I seem to be having a problem with the namespace.
My question is: How do I remove those namespaces? I read the data from an XML file.
Thank you!
I found the answer above to be helpful, but it didn't quite work for me.
This ended up working better:
// Gets rid of all namespace definitions
$xml_string = preg_replace('/xmlns[^=]*="[^"]*"/i', '', $xml_string);
// Gets rid of all namespace references
$xml_string = preg_replace('/[a-zA-Z]+:([a-zA-Z]+[=>])/', '$1', $xml_string);
If you're using XPath then it's a limitation with XPath and not PHP look at this explanation on xpath and default namespaces for more info.
More specifically its the xmlns="" attribute in the root node which is causing the problem. This means that you'll need to register the namespace then use a QName thereafter to refer to elements.
$feed = simplexml_load_file('http://www.sitepoint.com/recent.rdf');
$feed->registerXPathNamespace("a", "http://www.domain.com/schema/data");
$result = $feed->xpath("a:Data/a:Something/...");
Important: The URI used in the registerXPathNamespace call must be identical to the one that is used in the actual XML file.
The following PHP code automatically detects the default namespace specified in the XML file under the alias "default". No all xpath queries have to be updated to include the prefix default:
So if you want to read XML files rather they contain an default NS definition or they don't and you want to query all Something elements, you could use the following code:
$xml = simplexml_load_file($name);
$namespaces = $xml->getDocNamespaces();
if (isset($namespaces[''])) {
$defaultNamespaceUrl = $namespaces[''];
$xml->registerXPathNamespace('default', $defaultNamespaceUrl);
$nsprefix = 'default:';
} else {
$nsprefix = '';
}
$somethings = $xml->xpath('//'.$nsprefix.'Something');
echo count($somethings).' times found';
When you just want your xml, parsed to be used, and you don't care for any namespaces,
you just remove them. Regular expressions are good, and way faster than my method below.
But for a safer approach when removing namespaces, one could parse the xml with SimpleXML and ask for the namespaces it has, like below:
$xml = '...';
$namespaces = simplexml_load_string($xml)->getDocNamespaces(true);
//The line bellow fetches default namespace with empty key, like this: '' => 'url'
//So we remove any default namespace from the array
$namespaces = array_filter(array_keys($namespaces), function($k){return !empty($k);});
$namespaces = array_map(function($ns){return "$ns:";}, $namespaces);
$ns_clean_xml = str_replace("xmlns=", "ns=", $xml);
$ns_clean_xml = str_replace($namespaces, array_fill(0, count($namespaces), ''), $ns_clean_xml);
$xml_obj = simplexml_load_string($ns_clean_xml);
Thus you hit replace only for the namespaces avoiding to remove anything else the xml could have.
Actually I am using it as a method:
function refined_simplexml_load_string($xml_string) {
if(false === ($x1 = simplexml_load_string($xml_string)) ) return false;
$namespaces = array_keys($x1->getDocNamespaces(true));
$namespaces = array_filter($namespaces, function($k){return !empty($k);});
$namespaces = array_map(function($ns){return "$ns:";}, $namespaces);
return simplexml_load_string($ns_clean_xml = str_replace(
array_merge(["xmlns="], $namespaces),
array_merge(["ns="], array_fill(0, count($namespaces), '')),
$xml_string
));
}
To remove the namespace completely, you'll need to use Regular Expressions (RegEx). For example:
$feed = file_get_contents("http://www.sitepoint.com/recent.rdf");
$feed = preg_replace("/<.*(xmlns *= *[\"'].[^\"']*[\"']).[^>]*>/i", "", $feed); // This removes ALL default namespaces.
$xml_feed = simplexml_load_string($feed);
Then you've stripped any xml namespaces before you load the XML (be careful with the regex through, because if you have any fields with something like:
<![CDATA[ <Transfer xmlns="http://redeux.example.com">cool.</Transfer> ]]>
Then it will strip the xmlns from inside the CDATA which may lead to unexpected results.