How to count nodes of an xml file with php? - php

I know that maybe is a duplicate but doesn't works....
I have this xml
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
<Document>
<name>EMSC - Last 2 Weeks earthquakes worldwide</name>
<Folder>
<name>2017 7 - 13</name>
</Folder>
<Folder>
<name>2017 7 - 12</name>
</Folder>
</Document>
</kml>
i want count node Folder, i tied this
$pars_emsc= simplexml_load_file('/file');
$count_folder_emsc= $pars_emsc-> Document -> getElementsByTagName('Folder')->length;
but doesn't work...

You can't use the simple XML parser as a DOM document. Quite simply getElementsByTagName doesn't exist in SimpleXML. Use this instead:
$pars_emsc = new DOMDocument( "1.0", "ISO-8859-15" );
$pars_emsc->load("/file");
$count_folder_emsc= $pars_emsc->getElementsByTagName("Document")[0]->getElementsByTagName('Folder')->length;
print_r($count_folder_emsc);
Alternatively just do:
$pars_emsc= simplexml_load_file("/file");
$count_folder_emsc= $pars_emsc-> Document -> Folder -> count();

Xpath expressions can count nodes, too.
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('kml', 'http://www.opengis.net/kml/2.2');
var_dump($xpath->evaluate('count(//kml:Folder)'));
Output:
float(2)
You XML uses a default namespace, so you have to register a prefix for it.

Related

How to get into into another child than 'firstChild' of XML file in PHP?

How can I get through another child of XML file than firstChild in PHP?
I have a code like this:
$root = $xmldoc->firstChild;
Can I simply get into second child or another?
A possible solution to your problem could be something like this. First your XML structure. You asked how to add an item node to the data node.
$xml = <<< XML
<?xml version="1.0" encoding="utf-8"?>
<xmldata>
<data>
<item>item 1</item>
<item>item 2</item>
</data>
</xmldata>
XML;
In PHP one possible solution is the DomDocument object.
$doc = new \DomDocument();
$doc->loadXml($xml);
// fetch data node
$dataNode = $doc->getElementsByTagName('data')->item(0);
// create new item node
$newItemNode = $doc->createElement('item', 'item 3');
// append new item node to data node
$dataNode->appendChild($newItemNode);
// save xml node
$doc->saveXML();
This code example is not tested. Have fun. ;)

Need to find translation based on ID in xml

I have a xml file and I am confused how to find translation tag using the id tag which lie inside a message element.
What is the easiest way to look in name=menu and print the translation whose id=1
Here is my xml:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="en_GB" sourcelanguage="en_GB">
<context>
<name>Menu</name>
<message>
<id>1</id>
<source>Home</source>
<translation>Home</translation>
</message>
<message>
<id>25</id>
<source>About</source>
<translation>About</translation>
</message>
</context>
<context>
<name>Web</name>
<message>
<id>59</id>
<source>Welcome to </source>
<translation>Welcome to </translation>
</message>
<message>
<id>68</id>
<source>Happy</source>
<translation>Happy</translation>
</message>
</context>
</TS>
Use a XML parser for this. In this example, I will use built-in DOMDocument with DOMXPath:
$dom = new DomDocument();
$dom->loadXML( $xml );
$xpath = new DOMXPath( $dom );
$nodes = $xpath->query( '//context/message/id[.=25]/../translation' );
echo $nodes->item(0)->nodeValue;
Will print:
About
->loadXML( $xml ) loads your XML string, to load a file use ->load( $filePath ) instead.
The xpath syntax allow to performs short, complex queries. Above xpath means:
/ Root element
TS/context/message Descendant tree
/id[.=25] tag `<id>` with 25 as node value
/.. `<id>` parent tag (<message>)
/translation `<translation>` child
With this query we select all nodes with that matches above pattern (one node, in your case); the result is a group of nodes, so to refer to a node we have to use ->item(n) syntax. To extract its content, we use ->nodeValue.
In my example I use a complete-tree syntax, but in your XML <id> is in unique tree position, so you can short xpath query in this way:
//id[.=25]/../translation
The // at start means “Select following pattern no matter where they are in the document”.

SimpleXML: How to parse nodenames including dots with xpath query

I have to parse the following XML:
<BMECAT version="2005" xmlns="http://www.bmecat.org/bmecat/2005fd">
<T_NEW_CATALOG prev_version="0">
<PRODUCT>
<NAME>Test</NAME>
<USER_DEFINED_EXTENSIONS>
<UDX.VENDOR.ATTRIBUTE lang="de">German</UDX.VENDOR.ATTRIBUTE>
<UDX.VENDOR.ATTRIBUTE lang="en">English</UDX.VENDOR.ATTRIBUTE>
</USER_DEFINED_EXTENSIONS>
</PRODUCT>
</T_NEW_CATALOG>
</BMECAT>
I need to get the value "German" via xpath. Everything I have tried so far didn't work so I need some help. I think the problem is that the tagname includes dots. I have found no way to escape the xpath expression.
The XML you show cannot be parsed because it is malformed (USER_DEFINED_EXTENSIONS is not closed properly). Assuming well-formed input, you could use DOMDocument instead of SimpleXML:
<?php
$xml = <<<'XML'
<BMECAT version="2005" xmlns="http://www.bmecat.org/bmecat/2005fd">
<T_NEW_CATALOG prev_version="0">
<PRODUCT>
<NAME>Test</NAME>
<USER_DEFINED_EXTENSIONS>
<UDX.VENDOR.ATTRIBUTE lang="de">German</UDX.VENDOR.ATTRIBUTE>
<UDX.VENDOR.ATTRIBUTE lang="en">English</UDX.VENDOR.ATTRIBUTE>
</USER_DEFINED_EXTENSIONS>
</PRODUCT>
</T_NEW_CATALOG>
</BMECAT>
XML;
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
$xpath->registerNamespace("bme",
"http://www.bmecat.org/bmecat/2005fd");
$expression = 'string(
/bme:BMECAT
/bme:T_NEW_CATALOG
/bme:PRODUCT
/bme:USER_DEFINED_EXTENSIONS
/bme:UDX.VENDOR.ATTRIBUTE[#lang = "de"]
)';
var_dump($xpath->evaluate($expression));
And the result will be
German
If you need to use SimpleXML, you really need to show your current PHP code.

Get Child Node XML With DomDocument PHP

I have read instruction of DomDocument PHP, and try to get specific child from xml file, here the example
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<methods>
<index>
<title>User</title>
<meta_description>Description part</meta_description>
<meta_keywords>keywords parts</meta_keywords>
<permissions>permissions part</permissions>
<layout>layout parts</layout>
<css>css parts</css>
</index>
<update>
<title>update part</title>
<permissions>update_user</permissions>
</update>
</methods>
</configuration>
What I want is, let say I want to access permissions value tag of index tag, then how to do that? And how to check if permissions tag is exists on index tag with domdocument php.
Here, what I have done
$xml = new DOMDocument();
$xml->load(__DIR__ . DIRECTORY_SEPARATOR . 'configuration.xml');
$configurations['title'] = $xml->getElementsByTagName('index title')->nodeValue;
print_r($configurations);
The argument of DOMDocument::getElementsByTagName() is a single node name and it always returns a node list. For more complex and flexible expressions you need to use XPath:
$dom = new DOMDocument();
$dom->load(__DIR__ . DIRECTORY_SEPARATOR . 'configuration.xml');
$xpath = new DOMXPath($dom);
$configurations['title'] = $xpath->evaluate('string(//index/title)');
var_dump($configurations);
Output:
array(1) {
["title"]=>
string(4) "User"
}

Adding in new XML root node

I need to add in a new root node to the following XML
<?xml version="1.0"?>
<unit>
<source>
<id>ANCH02</id>
<uri>http://www.hamiltonisland.biz/tabid/339/Default.aspx</uri>
</source>
</unit>
to become
<?xml version="1.0"?>
<units>
<unit>
<source>
<id>ANCH02</id>
<uri>http://www.hamiltonisland.biz/tabid/339/Default.aspx</uri>
</source>
</unit>
</units>
How could I do this? It doesn't seem like SimpleXMLElement has this functionality. I have also looked at this DomNode example http://php.net/manual/en/domnode.insertbefore.php but it doesnt seem to be able to add in a new root node.
This seem to work
$units = $dom->createElement('units');
$units->appendChild($dom->documentElement);
$dom->appendChild($units);
DEMO
DOMDocument:
$yourDOMDOMDocument ... <--- already loaded XML
$doc = new DOMDocument();
$doc->appendChild($doc->createElement('Units'));
$doc->documentElement->appendChild($doc->importNode($yourDOMDocument->documentElement));
Or. if you have your XML as SimpleXMLElement already:
$yourSimpleXML ... <--- already loaded XML
$doc = new DOMDocument();
$doc->appendChild($doc->createElement('Units'));
$domnode = dom_import_simplexml($yourSimpleXML);
$doc->documentElement->appendChild($doc->importNode($domnode));
//if you want it back as SXE:
$newSimpleXMLElement = simplexml_import_dom($doc);

Categories