Having a xml file so formed:
<book id="1">
<chapter id="1">
...
</chapter>
<chapter id="2">
...
</chapter>
<chapter id="3">
...
</chapter>
</book>
How i can count nodes inside ... ?
In example above, the function should be turn 3 as result becouse present three nodes.
NOTE:
I access to ... so:
$xpath = new DOMXPath($filename);
$book = $xpath->query("//book[#id='1']")->item(0);
You can do as:
Refer: http://de2.php.net/manual/en/book.dom.php
$dom->getElementsByTagName('chapter')->length;
Unless you can use this:
$xpath->evaluate('count(//book/chapter');
Try this code
function xml2array($xmlObject, $out = array()) {
foreach ((array) $xmlObject as $index => $node)
$out[$index] = ( is_object($node) ) ? xml2array($node) : $node;
return $out;
}
$a = '<book>
<chapter id = "1">
...
</chapter>
<chapter id = "2">
...
</chapter>
<chapter id = "3">
...
</chapter>
</book>';
$a = simplexml_load_string($a);
$array=xml2array($a);
echo count($array['chapter']);
EDIT
Using DOMXpath try this
echo $book = $xpath->query("//book[#id='1']/chapter")->length;
Related
How do i get All Attribute Value ID of every node FLOWER?
<Files>
<data id="1">
<Type>Flower</Type>
</data>
<data id="2">
<Type>Flower</Type>
</data>
<data id="3">
<Type>Flower</Type>
</data>
<data id="4">
<Type>Flower</Type>
</data>
</Files>
In mysql case it will be like SELECT id from Files WHERE Type="Flower"
How do i code xpath for this condition?
and List it using SimpleXML within option box.
<select>
<?php
foreach ($type as $id) {
echo '<option value="'.$id.'">'.$id.'</option>';
}
?>
</select>
To get all #id attribute's values try
/Files/data[normalize-space(Type) = 'Flower']/#id
'//data[(./Type/text()="Flower")]/#id'
Your XML is invalid, the closing root element does not match and the Type elements are closed as type. XML is case sensitive.
Xpath works uses location paths and conditions a location path is a hierarchical path to the element from the current context. They return a list of nodes. The list can be filtered using conditions.
SimpleXMLElement objects have a method xpath() to execute an expression in the context of the associated node.
$xml = <<<'XML'
<Files>
<data id="1">
<type>Flower</type>
</data>
<data id="2">
<type>Flower</type>
</data>
<data id="3">
<type>Flower</type>
</data>
<data id="4">
<type>Flower</type>
</data>
</Files>
XML;
$files = new SimpleXMLElement($xml);
$target = new SimpleXMLElement('<select/>');
foreach ($files->xpath('data[type = "Flower"]') as $data) {
echo '.';
$option = $target->addChild('option', $data['id']);
$option['value'] = $data['id'];
}
echo $target->asXml();
You should not create you XML as text. Use an XML Api for it.
DOM is more specific and powerful. For example you can serialize the created DOM as HTML.
$source = new DOMDocument();
$source->loadXml($xml);
$xpath = new DOMXpath($source);
$target = new DOMDocument();
$select = $target->appendChild($target->createElement('select'));
foreach ($xpath->evaluate('/Files/data[type = "Flower"]') as $data) {
$option = $select->appendChild($target->createElement('option'));
$option->setAttribute('value', $data->getAttribute('id'));
$option->appendChild($target->createTextNode($data->getAttribute('id')));
}
echo $target->saveHtml($select);
This is how i used the answer Feel free to use the code if you like.
Thanks!!
<?php
//I have used 2 given answer as example on how i used it. Feel Free to use the code below
$type = $_GET['type'];
if(file_exists("xml/data.xml")) {
$xml = simplexml_load_file('xml/data.xml') or die("Data Missing"); }
<!-- Code Example 1 -->
$ids = $xml->xpath('//data[(./Type/text()="'.$type.'")]/#id');
<!-- Code Example 2 -->
$idx = $xml->xpath('/Files/data[normalize-space(Type) = "'.$type.'"]/#id');
?>
<!-- Example 1 -->
<select>
<?php
//echo $ids[0];
foreach ($ids as $id) {
echo '<option value="'.$id[0].'">'.$id[0].'</option>';
}
?>
</select>
<!-- Example 2 -->
<select>
<?php
//echo $ids[0];
foreach ($idx as $id2) {
echo '<option value="'.$id2[0].'">'.$id2[0].'</option>';
}
?>
</select>
<a href="logout.php">Logout
</a>
I'm having some problems with adding a xml node to its parent.
I receive variables $cat, $title and $isbn.
I want to parse $title and $isbn to an XML node and add it to the right categorie ($cat).
die(var_dump($parent)); --> returns NULL, so the biggest problem (I think) is that I can't figure out how to add my node to the right parent because I cant get it identified.
Any suggestions?
The XML file:
<?xml version="1.0"?>
<books version="1.0">
<categorie name="catone" id="100">
<book title="1_WS2012" isbn="isbnone" />
<book title="1W2012DHCP" isbn="ibsntwo" />
</categorie>
<categorie title="cattwo" id="101">
<book title="2W2008R2DC" isbn="isbnthree" />
</categorie>
<categorie title="catthree" id="103">
<book title="3SBS" isbn="isbnfout=" />
</categorie>
</books>
The Code:
//Get variables
$cat = "catone";
$title = "testtitle";
$isbn = "testisbn";
$xmlDoc = simplexml_load_file("books.xml");
$parent = null;
//Construct node
$childstring = "<book></book>";
$child = new SimpleXMLElement($childstring);
$child->addAttribute('title', $title);
$child->addAttribute('isbn', $isbn);
//This works (results in <book title="testtile" isbn="testisbn" />)
//Add node to correct parent
for ($i=0; $i <= sizeof($xmlDoc->categorie) -1; $i++) {
//The condition does also work
if (strtoupper($xmlDoc->categorie[$i]->attributes()->name) == strtoupper($cat))
{
//I'm stuck here
$parent = $xmlDoc->categorie[$i]->attributes()->xpath('/object/data[#type="me"]');;
$xmlDoc->$parent->addChild($child);
}
}
//Write file
file_put_contents("books.xml", $xmlDoc->asXML());
Desired result:
<books version="1.0">
<categorie name="catone" id="100">
<book title="1_WS2012" isbn="isbnone" />
<book title="1W2012DHCP" isbn="ibsntwo" />
<book title="testtitle" isbn"testisbn" />
</categorie>
<categorie title="cattwo" id="101">
<book title="2W2008R2DC" isbn="isbnthree" />
</categorie>
<categorie title="catthree" id="103">
<book title="3SBS" isbn="isbnfout=" />
</categorie>
</books>
First, use xpath to select the parent. xpath is like SQL for XML:
$xml = simplexml_load_string($x); // assume XML in $x
$parent = $xml->xpath("/books/categorie[#name = 'catone']")[0];
Note: The above code requires PHP >= 5.4 for the [0] at the end of line 2. (1)
Now, add the new <book> and its attributes:
$new = $parent->addChild("book","");
$new->addAttribute("title", "testtitle");
$new->addAttribute("isbn", "testisbn");
see it working: https://eval.in/131009
(1) if you are on PHP < 5.4, either update or do:
$parent = $xml->xpath("/books/categorie[#name = 'catone']");
$parent = $parent[0];
Suppose I have the following XML:
<Book>
<bookname>thename</bookname>
<chapters>
<chapter>
<name>chapter1</name>
</chapter>
<chapter>
<name>chapter2</name>
</chapter>
</chapters>
</Book>
How can I get an XML as follows:
<chapters>
<chapter>
<name>chapter1</name>
</chapter>
<chapter>
<name>chapter2</name>
</chapter>
</chapters>
One way is to manually remove unwanted elements e.g
$resultXML = new SimpleXMLElement($inputXML);
unset($resultXML->bookname);
$resultXML = $resultXML->asXml();
echo format_result($resultXML,$format);
But if I have a large XML with many unwanted notes, this is tedious. Any idea who to extract the required element using its name?
The sub-nodes of your XML are themselves SimpleXMLElements – so you can just call the axXml method on them as well.
Since you only have one chapters node in your XML, simply
$resultXML->chapters->asXml()
will do.
Here we go:
<?php
$inputXML ="
<Book>
<bookname>thename</bookname>
<chapters>
<chapter>
<name>chapter1</name>
</chapter>
<chapter>
<name>chapter2</name>
</chapter>
</chapters>
</Book>
";
/* Load from file:
$parseXML = simplexml_load_file( $fileURL );
*/
$parseXML = simplexml_load_string( $inputXML );
$chapters = $parseXML->chapters->asXML();
echo $chapters;
?>
Note: Your xml must be well-formated, currently your <Book> has no closing tag.
ornek.xml here :
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book onay="e" katid="31" dil="tr">
<kitapadi>Dear Lovely</kitapadi>
<yazar>Author 1234</yazar>
<isbn>1234513</isbn>
</book>
<book onay="e" katid="32" dil="en">
<kitapadi>Love and Hate</kitapadi>
<yazar>Author 345</yazar>
<isbn>1234513</isbn>
</book>
</library>
PHP Code:
$xml = simplexml_load_file('veri/ornek.xml');
$search= '34';
$result = $xml->xpath('//yazar[contains(.,"'.$search.'")]');
foreach($result as $tt){
echo $tt;
}
If I use this, I can get the yazar attributes. But I want get another attributes
example:
$search = 34 where match yazar 34 giving this block in kitapadi,isbn,yazar
If you like to get the book containing a serach sring in yazar. Use something like this:
$xml = simplexml_load_file('veri/ornek.xml');
$search= "34";
$result = $xml->xpath("//book[yazar[contains(.,' $search')]]");
foreach($result as $tt){
echo $tt->isbn;
}
This XPath query does the trick:
//*[text()[contains(., '34')]]
Result:
Element='<yazar>Author 1234</yazar>'
Element='<isbn>1234513</isbn>'
Element='<yazar>Author 345</yazar>'
Element='<isbn>1234513</isbn>'
Consider the following code :
$dom = new DOMDocument();
$dom->loadXML($file);
$xmlPath = new DOMXPath($dom);
$arrNodes = $xmlPath->query('*/item');
foreach($arrNodes as $item){
//missing code
}
The $file is an xml and each item has a title and a description.
How can I display them (title and description)?
$file = "<item>
<title>test_title</title>
<desc>test</desc>
</item>";
I suggest using php's simplexml, with that, you still get xpath functionality, but with easier approach, for example you would access attributes like this:
$name = $item['name'];
Here's an example:
xmlfile.xml:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<items>
<item title="Hello World" description="Hellowing the world.." />
<item title="Hello People" description="greeting people.." />
</items>
</xml>
do.php:
<?php
$xml_str = file_get_contents('xmlfile.xml');
$xml = new SimpleXMLElement($xml_str);
$items = $xml->xpath('*/item');
foreach($items as $item) {
echo $item['title'], ': ', $item['description'], "\n";
}
If your item looks like this:
<item>
<title>foo</title>
<description>frob</description>
</item>
You could use getElementsByTagName() and nodeValue:
foreach($arrNodes as $item){
print $item->getElementsByTagName('title')->item(0)->nodeValue;
}
Are title and description attributes? E. g. does an item look like this:
<item title="foo" description="frob" />
If so, you could just use getAttribute():
...
foreach($arrNodes as $item){
print $item->getAttribute('title');
}
The right XPath expression should be:
/*/item/title | /*/item/desc
Or
/*/item/*[self::title or self::desc]
This is evaluate to a node set with title and desc element in document order