xpath with namespace - php

I am trying to use xpath in php SimpleXML with an xml file, of which the following is a relevant fragment:-
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
- <!-- Created on 21-Mar-2012 10:30:46
-->
- <message:Structure xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/structure" xmlns:message="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message" xsi:schemaLocation="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/structure http://www.sdmx.org/docs/2_0/SDMXStructure.xsd http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message http://www.sdmx.org/docs/2_0/SDMXMessage.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <Header xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message">
<ID>none</ID>
<Test>false</Test>
<Truncated>false</Truncated>
<Prepared>2011-11-18T13:56:45</Prepared>
- <Sender id="OECD">
<Name xml:lang="en">Organisation for Economic Co-operation and Development</Name>
<Name xml:lang="fr">Organisation de coopération et de développement économiques</Name>
</Sender>
</Header>
- <message:CodeLists>
- <CodeList id="CL_MEI_OBS_STATUS" agencyID="OECD">
<Name xml:lang="en">Observation Status</Name>
<Name xml:lang="fr">Statut d'observation</Name>
- <Code value="B">
<Description xml:lang="en">Break</Description>
<Description xml:lang="fr">Rupture</Description>
</Code>
etc. etc.
In my php code I have the following, which registers the namespace then uses xpath to obtain CodeLists:-
$xml->registerXPathNamespace('test','http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message');
$codelistspath = $xml->xpath('test:CodeLists');
I would like to be able to use xpath to go one level lower in the tree, i.e. to CodeList and thought the following would work:-
$codelistpath = $xml->xpath('test:CodeLists/CodeList');
But it just produces an empty array. I can find no way of accessing anything else in the document with xpath. I have spent hours trying to solve this, so any help would be greatly appreciated.

The CodeList elements belong to the default namespace inherited from the <message:Structure> element - the namespace whose URI is http://www.SDMX.org/resources/SDMXML/schemas/v2_0/structure.
You will need to register that with registerXPathNamespace() as well.
$xml->registerXPathNamespace('default', 'http://www.SDMX.org/resources/SDMXML/schemas/v2_0/structure');
$codelistpath = $xml->xpath('test:CodeLists/default:CodeList');

It looks like registerXPathNamespace only works for the next xpath query (according to the documentation)... so if you've run $xml->xpath('test:CodeLists') already, try registering the namespace again before running $xml->xpath('test:CodeLists/CodeList').

Related

How to parse xml subtree in php

Hello have worten some php code to parse a xml file as long if i use seperate fields this works like a charm but how i can call a subtree ?
like eg :
<item>
<items>
<date>
<from>2020-03-23</from>
<until>2020-03-27</until>
</date>
</items>
</item>
```
I assume with subtree you mean an element within an element etc.
PHP offers a built in solution for this: simplexml_load_string
$xml = <<<BLOCK
<item>
<items>
<date>
<from>2020-03-23</from>
<until>2020-03-27</until>
</date>
</items>
</item>
BLOCK;
var_dump(simplexml_load_string($xml));
You can read a file directly aswell by using simplexml_load_file.
i have found a solution for this problem i have done the following:
<?php
error_reporting(E_ALL);
$xml_file = simplexml_load_file("converted.xml");
echo $xml_file->date[0]->from;
echo $xml_file->date[0]->until;
?>
```

simplexml load multiple files at once

I'm using XML to fetch some language data.
The XML markup is as follows:
<language>
<item>
<key>KEY</key>
<string>STRING</string>
</item>
<item>
....
</item>
</language>
I have 2 XML-files with the same markup. I want to load them both with simplexml_load_file. Does anyone know what's the best approach to do this?
I tried something like this:
<?php
$xml = simplexml_load_file('...url_file_1...');
$xml .= simplexml_load_file('...url_file_2...');
?>
But thats not working. But thats what I want: all the data from the 2 (and eventually more) files in one variable.
Edit: I want to make use of the simpleXML library if possible.

How to extract in php this type of XML format?

How to extract in php this type of XML format? i try 'simplexml_load_file' function but its not work, it work only normal xml format.
Thanks in advance :)
<?xml version="1.0"?>
<a:p>
<a:r>
<a:rPr strike="noStrike" u="none" b="0" cap="none" baseline="0" sz="1400" lang="en-US" i="0">
<a:solidFill>
<a:srgbClr val="595959"/>
</a:solidFill>
<a:latin typeface="Arial"/>
<a:ea typeface="Arial"/>
<a:cs typeface="Arial"/>
<a:sym typeface="Arial"/>
</a:rPr>
<a:t>E-mail Address</a:t>
</a:r>
The XML you show isn't well-formed, meaning it doesn't match the structure of what XML should look like. Specifically, the <a:p> element on line 2 doesn't have an ending tag, </a:p>.
Adding that ending tag should make simplexml_load_string work, but you'll also get warnings because of having an undefined namespace, a. The a: that's part of each element name is saying those elements are part of a namespace whose alias is a. To fix this, you would add an attribute to your root element to define that alias, like this: <a:p xmlns:a="some-namespace"> (replace some-namespace with the actual namespace for the XML content you're using, obviously--this looks like it could be the content of an MS Word Document, so the namespace might be something like http://schemas.microsoft.com/office/word/2003/wordml, as a guess).
Once you start using the namespace correctly, though, you'll have to inform simplexml_load_string that the content you're loading is in that namespace; this is done via the fourth argument to the function, ns.
A complete, working example is:
<?php
$content = <<<XML
<?xml version="1.0"?>
<a:p xmlns:a="some-namespace">
<a:r>
<a:rPr strike="noStrike" u="none" b="0" cap="none" baseline="0" sz="1400" lang="en-US" i="0">
<a:solidFill>
<a:srgbClr val="595959"/>
</a:solidFill>
<a:latin typeface="Arial"/>
<a:ea typeface="Arial"/>
<a:cs typeface="Arial"/>
<a:sym typeface="Arial"/>
</a:rPr>
<a:t>E-mail Address</a:t>
</a:r>
</a:p>
XML;
$xml = simplexml_load_string($content, "SimpleXMLElement", 0, "some-namespace");
print_r($xml);
?>
Obviously, you'd normally be reading the XML from a file or some such, but I included it inline in a heredoc for simplicity.
You can look at the simplexml_load_string and SimpleXMLElement documentation for additional helpful details.

update element from node in XML

First of all, I just found this site a few days ago and am very happy it exists.
I am facing a problem with updating a child element from a XML Node.
The xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="books.xsl"?>
<books>
<book>
<id>1</id>
<bookname>Title 1</bookname>
<bookurl>SomeURLToMyBook</bookurl>
<clicks>0</clicks>
</book>
<book>
<id>2</id>
<bookname>Title 2</bookname>
<bookurl>SomeURLToMyBook</bookurl>
<clicks>0</clicks>
</book>
</books>
I do know how to retrieve the node for book with (e.g.) ID 2 using:
$xml= simplexml_load_file('books.xml);
I then use xpath to find the correct node. as in:
$booknum= $_GET('booklist'); //booklist is the parameter in the querystring
$arrOutput = $xml->xpath("//*[id='".$booknum."']");
What I try to achieve is to update the clicks element and then save the outcome into the existing XML.
I found several code examples on this site but neither one seems to work for me.
I probably do something wrong but I am not really familiar with PHP (learning new things every day!)
So if anybody is willing to help me out I would be grateful.
TIA

How can I delete a child from an XML file via simplexml?

I've got the following xml file:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<number_of_gr>
3
</number_of_gr>
<group id="0">
<name>Admins</name>
<backend>1</backend>
<every_plugin_feature> 1 </every_plugin_feature>
</group>
<group id="1">
<name>Users</name>
<backend>0</backend>
<every_plugin_feature>0</every_plugin_feature>
</group>
<group id="2">
<name>Moderators</name>
<backend>0</backend>
<every_plugin_feature>0</every_plugin_feature>
</group>
</root>
For Example: I want to delete the group with the id="0". But I don't know how to delete a child with specified attribute in simplexml.
I've tried this code:
<?php
$xml = simplexml_load_file("../xml/groups.xml");
$delgroup = $xml->xpath("/root/group[#id='".$_GET['group']."'");
unset($delgroup);
$xml-> asXML("../xml/groups.xml");
?>
But it doesn't work.
After the process, I'll fill the gap with the id=1, but I can do it without help.
My question is: How to delete the specified group?
You are almost there, just a little tweak:
$delgroup = $xml->xpath("//group[#id='".$_GET['group']."'")[0];
unset($delgroup[0]);
see it working: http://codepad.viper-7.com/ZVXs4O
This requires PHP >= 5.4.
To see a bit of theory behind it: Remove a child with a specific attribute, in SimpleXML for PHP --> see hakre's answer.
PS: Remember to change <number_of_gr> - or delete this node from the XML, because you can always get this number by...
$groups = $xml->xpath("//group");
$numberofgroups = count($groups);

Categories