I have this XML file and I need to replace te value of qteStock using the php DOM,but I still can't get the concept.Can anyone help me please?
<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="Marque.xsl" ?>
<Marques xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="Marques.xsd">
<Marque>
<codeMarque>00003</codeMarque>
<nomMarque>Diesel</nomMarque>
<paysOrigine>USA</paysOrigine>
<qteStock>50</qteStock>
<qteLimite>5</qteLimite>
</Marque>
</Marques>
This is the php code I've been trying to manipulate:
<?php
$marque=$_POST['nomMarque'];
$qte=$_POST['qte'];
$xmlstring = 'entities/Marques.xml';
$dom = new DOMDocument;
$dom->load($xmlstring);
$xpath = new DOMXPath($dom);
$query = "//Marque[nomMarque='".$marque."']/qteStock";
$qteStock = $xpath->query($query);
$query = "//Marque[nomMarque='".$marque."']/qteLimite";
$qteLimite = $xpath->query($query);
$nouvelleQuantite = $qteStock->item(0)->nodeValue-$qte ;
$newQuantity = $dom->createTextNode($nouvelleQuantite);
$return = ($qteStock->replaceChild($newQuantity,$qteStock);
$dom->save('entities/Marques.xml');
?>
You can set the nodeValue property of the element node - integers do not need escaping in XML. If you need to write text that could contain &, set the nodeValue to an empty string (deletes all child nodes) and insert a new text node.
$changeValue = 5;
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$nodes = $xpath->evaluate('/Marques/Marque[1]/qteStock');
// node found?
if ($nodes->length > 0) {
$stock = $nodes->item(0);
$newValue = $stock->nodeValue - $changeValue;
// just set the content (an int does not need any escaping)
$stock->nodeValue = (int)$newValue;
}
echo $dom->saveXml();
Demo: https://eval.in/149098
Related
i have an xml file and a php file.i have received a result from an the xml file but i am not being able to get the different values of the tags.what i want is the data from individual tags.Any idea how to do it?
Here is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<users xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<user>
<id>1</id>
<username>neem99</username>
<password>dbhcasvc</password>
<email>vgwdevwe#hfvuejd.com</email>
</user>
</users>
Sample php file:
$xp = new DOMXPath( $dom );
echo var_dump($xp);
$col = $xp->query( $query );
echo var_dump($col);
$array = array();
if( $col->length > 0 ){
foreach( $col as $node) echo $node->nodeValue
}
result : 1 neem99 dbhcasvc vgwdevwe#hfvuejd.com
DOMXpath::evaluate() allows to use Xpath expressions that return scalar values. string() casts a list of nodes to a string by returning the text content of the first node.
Demo:
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
// get first user id
var_dump($xpath->evaluate('string(/users/user/id)'));
//iterate all user nodes
foreach ($xpath->evaluate('/users/user') as $user) {
// get its username
var_dump($xpath->evaluate('string(username)', $user));
}
I would do like:
$doc = new DOMDocument; #$doc->load('yourFileName.xml');
$user = $doc->getElementsByTagName('user');
foreach($user as $u){
echo 'nodeName:'.$u->nodeName.'; nodeValue:'.$u->nodeValue.PHP_EOL;
}
I have xml file
<root>
<param1_2014>1</param1_2014>
<param2_2014>2</param2_2014>
<param2_2015>3</param2_2015>
<param2_2015>4</param2_2015>
<param3_2015>5</param3_2015>
</root>
How I can get all nodes, which contains "2015" substring in tags? I can't search it in manual.
Thank you!
The xpath function contains is what you're after, just check the element names against your string.
Example:
$xml = <<<'XML'
<root>
<param1_2014>1</param1_2014>
<param2_2014>2</param2_2014>
<param2_2015>3</param2_2015>
<param2_2015>4</param2_2015>
<param3_2015>5</param3_2015>
</root>
XML;
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
foreach ($xpath->query("//*[contains(local-name(),'2015')]") as $node) {
echo $dom->saveXML($node), "\n";
}
Output:
<param2_2015>3</param2_2015>
<param2_2015>4</param2_2015>
<param3_2015>5</param3_2015>
If you want to limit it specifically to tags ending in "2015" it's a little more work. Sadly xpath 2 isn't supported or the xpath function ends-with would be perfect here, so you'll have to make do with substring.
Example:
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
$search = "2015";
$query = "//*[
substring(
local-name(),
string-length(local-name()) - string-length('$search') + 1
) = '$search'
]";
foreach ($xpath->query($query) as $node) {
echo $dom->saveXML($node), "\n";
}
Output:
<param2_2015>3</param2_2015>
<param2_2015>4</param2_2015>
<param3_2015>5</param3_2015>
Hi I am trying to clean up xml file out of positions I dont need. Here is my code so far:
<?php
$doc = new DOMDocument;
$doc->load('merg.xml');
$xpath = new DOMXPath($doc);
$products = $xpath->query('//offer/products/*');
printf('There is %d products<br /><br />', $products->length);
function findStopPointByName($xml, $query) {
$upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZĄŻŚĆŹĆÓŁ";
$lower = "abcdefghijklmnopqrstuvwxyzążśćźńół";
$arg_query = "translate('$query', '$upper', '$lower')";
return $xml->query("//offer/products/product/description/name[contains(text(),$arg_query)]");
}
foreach(findStopPointByName($xpath,'Skór') as $node)
{
$node->parentNode->removeChild($node);
}
$doc->save('merg_fixed.xml');
?>
Structure of XML:
<offer>
<products>
<product>
<description>
<name>Name of the product</name>
...
</name>
...
</description>
</product>
</products>
</offer>
I am trying to remove all PRODUCT where its NAME contains 'Skór' in any case (Skór, skór, SKÓR - is enough). Funcion findStopPointByName returns DOMNodeList of correct length, but nothing is removed from actual XML file, please help.
First, you can directly find node product with the condition
Second, to make search case insensitive, you can translate node text in any case but should use pattern in the same case. As the result, your code may be so
function findStopPointByName($xml, $query) {
$upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZĄŻŚĆŹĆÓŁ";
$lower = "abcdefghijklmnopqrstuvwxyzążśćźńół";
$arg_query = "translate(text(), '$upper', '$lower')";
$q = "//product[description/name[contains($arg_query, '$query')]]" ."\n";
return $xml->query($q);
}
$doc = new DOMDocument;
$doc->load('merg.xml');
$xpath = new DOMXPath($doc);
foreach(findStopPointByName($xpath,'skór') as $node)
$node->parentNode->removeChild($node);
echo $doc->saveXML();
Demo on eval.in
There's the sum-function in xpath:
<list>
<a>1</a>
<a>3</a>
<a>4</a>
</list>
Now with SimpleXml...
var_dump($xml->xpath("sum(/list/a)"));
delivers NULL instead of 8
What's wrong here?
see it not working: https://eval.in/135558
EDIT: I've used this workaround for SimpleXml to avoid iterating:
$sum = $xml->xpath("/list/a");
$sum = array_sum(array_walk("intval", $sum));
If you're using SimpleXML, you're going to have to do it manually. However, you can use DOMDocument to achieve this. Just use evaluate() method to evaluate the XPath expression:
$dom = new DOMDocument;
$dom->loadXML($xml); // $xml is the XML string
$xpath = new DOMXPath($dom);
$sum = (int) $xpath->evaluate('sum(/list/a)'); // => 8
Demo
SimpleXML solution:
$xml = simplexml_load_string($xml);
$sum = 0;
foreach ($xml->a as $node) {
$sum += (int) $node;
}
echo $sum; // => 8
Demo
Use DOMXPath::evaluate() here:
$str = <<<XML
<list>
<a>1</a>
<a>3</a>
<a>4</a>
</list>
XML;
$output = new SimpleXMLElement($str);
$doc = new DOMDocument();
$doc->loadXML($str);
$selector = new DOMXPath($doc);
var_dump($selector->evaluate('sum(//list/a/text())'));
// double(8)
Side-note: It will return a double not an integer. This might be surprising in the first place.
I have a little problem with creating an complex XML structure with PHP and Dom Document.
I want the structure to be like this:
<page PathToWeb="www.mysite.com">
<Questions>
<Question id="my id" member="true">
<Question id="my id2" member="true">
<Question id="my id3" member="true">
</Questions>
</page>
and the code i have so far is
<?php
/*Create DOM*/
$xml = new DOMDocument;
$xml->load('myxml.xml'); /* wich is just just blank <?xml?\> <page> </page>*/
$xpath = new DOMXPath($xml);
/*Set the base path*/
$hrefs = $xpath->evaluate("/page");
/*Add Path to web to the root /page*/
$href = $hrefs->item(0);
$href->setAttribute("PathToWeb",$PathToWeb);
/*Complex XML Creation with Xpath*/
/*ELEMENT APPEND (create questions into /page)*/
$href = $hrefs->item(0);
$element = $xml->createElement('Questions');
$href->appendChild($element);
/*XPATH EVALUATE*/
$hrefs = $xpath->evaluate("/page/Questions");
/*ELEMENT 1 APPEND*/
$href = $hrefs->item(0);
$element = $xml->createElement('Question');
$href->appendChild($element);
$hrefs = $xpath->evaluate("/page/Questions/Question");
$href = $hrefs->item(0);
$href->setAttribute("id","my id");
/*ELEMENT 2 APPEND*/
$href = $hrefs->item(0);
$element = $xml->createElement('Question');
$href->appendChild($element);
$hrefs = $xpath->evaluate("/page/Questions/Question");
$href = $hrefs->item(0);
$href->setAttribute("id","my id");
/*ELEMENT 3 APPEND*/
$href = $hrefs->item(0);
$element = $xml->createElement('Question');
$href->appendChild($element);
$hrefs = $xpath->evaluate("/page/Questions/Question");
$href = $hrefs->item(0);
$href->setAttribute("id","my id");
$href = $hrefs->item(0);
$href->setAttribute("member","true");
$string2 = $xml->saveXML();
?>
What is creating is:
<page PathToWeb="www.mysite.com">
<Questions><Question id="my id" member="true"><Question/></Question></Questions>
</page>
Editing only the first Question ...
How can i solve this?
Your code looks somewhat more complicated than it needs to be.
Because appendChild returns the appended node and setAttribute returns the set Attribute Node, you could also create the entire tree without any temp variables and also without any Xpath simply by chaining method calls and traversing the DOM tree:
$dom = new DOMDocument('1.0', 'utf-8');
$dom->appendChild($dom->createElement('page'))
->setAttribute('PathToWeb', 'www.mysite.com')
->parentNode
->appendChild($dom->createElement('Questions'))
->appendChild($dom->createElement('Question'))
->setAttribute('id', 'my_id')
->parentNode
->setAttribute('member', 'true')
->parentNode
->parentNode
->appendChild($dom->createElement('Question'))
->setAttribute('id', 'my_id2')
->parentNode
->setAttribute('member', 'true')
->parentNode
->parentNode
->appendChild($dom->createElement('Question'))
->setAttribute('id', 'my_id3')
->parentNode
->setAttribute('member', 'true');
$dom->formatOutput = true;
echo $dom->saveXml();
Understanding that DOM is a tree hierarchy of DOMNodes is essential when wanting to work with DOM. See DOMDocument in php for some explanation on that.
$xml = new DOMDocument('1.0','UTF-8');
$root = $xml->createElement('page');
$root->setAttribute("PathToWeb",$PathToWeb);
$wrap = $xml->createElement('Questions');
$root->appendChild($wrap);
for ($i = 1;$i<4;$i++)
{
$element = $xml->createElement('question');
$element->setAttribute("id","my id" . $i);
$element->setAttribute("member","true");
$wrap->appendChild($element);
}
$xml->appendChild($root);
$xml->formatOutput = true;
$xml->save('myxml.xml');// Thanks to Gordon
<?php
$xml = new DOMDocument;
$xml->load('myxml.xml'); /* wich is just just blank <?xml?> <page> </page>*/
$xpath = new DOMXPath($xml);
/*Set the base path*/
$base = $xpath->evaluate("/page")->item(0);
$base->setAttrubute("PathToWeb", $PathToWeb);
$questions = $xml->createElement('Questions');
$base->appendChild($questions);
for($i = 0; $i < 2; $i++) {
$question= $xml->createElement('Question');
$questions->appendChild($question);
$question->setAttribute("id","my id");
$question->setAttribute("member", "true");
}
$string2 = $xml->saveXML();
?>
This might help you to solve your problem and make your code much more compact and easier to deal with:
appendChild PHP Manual returns the new node. You can then directly work with it. No need to use xpath after appending the child to get access to it.
And if you add/set the attributes you want to set before adding the element node to the document, you most often don't even need to:
/*ELEMENT APPEND (create questions into /page)*/
$href = $hrefs->item(0);
$element = $xml->createElement('Questions');
$questions = $href->appendChild($element);
# ^^^
/*ELEMENT 1 APPEND*/
$element = $xml->createElement('Question');
$element->setAttribute("id","my id"); # prepare before adding
$questions->appendChild($element);
...
It's quite the same for the root element of your document (<page>). You do not need to use xpath to access it and manipulate it. It's documentElement PHP Manual:
/*Create DOM*/
$xml = new DOMDocument;
$xml->load('myxml.xml'); /* wich is just just blank <?xml?> <page> </page>*/
/*Add Path to web to the root /page*/
$href = $xml->documentElement;
$href->setAttribute("PathToWeb",$PathToWeb);