Im trying to save a specific node instead of the full xml file, but I get error.
Catchable fatal error: Argument 1 passed to DOMDocument::saveXML() must be an instance of DOMNode, instance of DOMNodeList given in php\corrdination.php on line 31
I'm following the doom documentation but since I don't create new element and only read from an already created xml file, it wont work with creating new elements.
My line 31 is
$resultX = $xpath->query('/stickers/sticker[id="200"]/position/x');
And when im trying to save only the changed node i write.
echo $xml->saveXML($resultX);
Any suggestion on how to do it ?
This is my whole php file.
$xml = new DOMDocument();
$xml->formatOutput = TRUE;
$xml->preserveWhiteSpace = FALSE;
$xml->load('../stickers.xml');
$xpath = new DOMXPath($xml);
$resultX = $xpath->query('/stickers/sticker[id="200"]/position/x');
$resultX->item(0)->nodeValue = "150";
echo $xml->saveXML($resultX);
If I only echo $xml->saveXML();
The query works but as I said, it saves the whole node structure.
XML file:
<stickers>
<sticker>
<position>
<x>0</x>
</position>
<text>Hello world </text>
<id>200</id>
</sticker>
</stickers>
Thanks
The error says you have to pass DOMNode to DOMDocument::saveXML(). So you need to change this line:
echo $xml->saveXML($resultX);
to this:
echo $xml->saveXML($resultX->item(0));
Related
I've tried the solution here: Getting attribute using XPath
but it gives me an error.
I have some XHTML like this:
Click me!
I'm recursively parsing the XML and trying to get both the href attribute (link.php) and the link text (Click me!) at the same time.
<?php
$node = $xpath->query('string(self::a/#href) | self::a/text()', $nodes->item(0));
This code throws the following error:
Warning: DOMXPath::query(): Invalid type
If I do either of these two separately they work, but not together:
<?php
$node = $xpath->evaluate('string(self::a/#href)', $nodes->item(0));
$node = $xpath->query('self::a/text()', $nodes->item(0));
If I use the following I get the whole attribute (href="link.php"), not just its value:
<?php
$node = $xpath->query('self::a/#href | self::a/text()', $nodes->item(0));
Is there any way of getting both text values at the same time using XPath 1.0 in PHP?
As suggested by others, you can use concat() (and PHP XPath supports it! see the demo below) to combine value of attribute and content of an element.
The problem with others' suggested XPath probably was, judging from your attempted code i.e the use of self::a, that the context node ($nodes->item(0)) is already the <a> element, so that a/#href relative to current context node means return href attribute of child element a of current element, that's why you got no match. You were correct by using self::a in this case or, alternatively, just . which can be used to reference current context node :
$doc = new DOMDocument();
$xml = <<<XML
<root>
Click me!
</root>
XML;
$doc->loadXML($xml);
$xpath = new DOMXpath($doc);
$nodes = $xpath->query('//a');
$node = $xpath->evaluate('concat(#href, "|", .)', $nodes->item(0));
echo $node;
eval.in demo
output :
link.php|Click me!
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'm trying to parse some html that is inside an external .dat file.
I would normaly use the follwing code:
$html = new DOMDocument();
$html->loadHTMLFile('http://www.bvl.com.pe/includes/cotizaciones_todas.dat');
$xpath = new DOMXPath($html);
$path = '/somepath';
$nodelist = $xpath->query($path);
echo $nodelist->item(0)->nodeValue;
But I'm getting this error:
DOMDocument::loadHTMLFile(): htmlParseEntityRef: expecting ';' in http://www.bvl.com.pe/includes/cotizaciones_todas.dat, line: 15
I know that the problem is the loadHTMLFile, I tried using load or loadXML but it's not working neither.
Any help would be appriciated.
UPDATE
To solve the problem I had to handle the errors using libxml_use_internal_errors(TRUE).
Now I've a new problem, I want to count how many <tr> tags are inside the table. I'm using the following code:
$html = new DOMDocument();
libxml_use_internal_errors(TRUE);
$html->loadHTMLFile('http://www.bvl.com.pe/includes/cotizaciones_todas.dat');
libxml_clear_errors();
$xpath = new DOMXPath($html);
$tbody = $html->getElementsByTagName('tbody')->item(0);
$path = 'count(tr)';
$trCount = $xpath->evaluate($path,$tbody);
But I'm getting this error msg: PHP Catchable fatal error: Argument 2 passed to DOMXPath::evaluate() must be an instance of DOMNode, null given I already used the same code with other files and everything worked fine, but in this case it's not working, maybe because the html is broken?
I am having a strange behavior in my script. That has me confused
Script 1.
$dom = new DOMDocument();
$dom->loadHTMLFile("html/signinform.html");//loads file here
$form = $dom->getElementsByTagName("form")->item(0);
$div = $dom->createElement("div");
$dom->appendChild($div)->appendChild($form);
echo $dom->saveHTML();
Script 2.
$dom = new DOMDocument();
$div = $dom->createElement("div");
$dom->loadHTMLFile("html/signinform.html");//loads file here
$form = $dom->getElementsByTagName("form")->item(0);
$dom->appendChild($div)->appendChild($form);
echo $dom->saveHTML();
Script 1 works without problem. It shows the form. However Script 2 throws the following error: Fatal error: Uncaught exception 'DOMException' with message 'Wrong Document Error' in C:\Users
Could someone explain to me why the mere changing of position of the loadHTMLFile function results in such error? Thanks
You have added an element to the DOM (div) and then attempted to load a file to be parsed and its DOM structure used.
Load the file first if you intend to use one.
For DOM manipulation you do not need to insert an already existing element so doing something like this: $dom->appendChild($form) only reinserts the same form element, when you pull an element using $dom->getElementsByTag("form")->item(0) it becomes it's own DOM object which you can reference directly and append to. A proper example would be:
$dom = new DOMDocument();
$dom->loadHTMLFile("assets/dom_document-form.html");
$div = $dom->createElement("div");
$form = $dom->getElementsByTagName("form")->item(0);
$form->appendChild($div);
echo $dom->saveHTML();
One should append directly to the object they pulled from the DOM instead and load the document first.
To help aid your initial questions too:
Append directly to element that you pulled as it references the object.
new DOMDocument can be used to create multiple documents.
using DOMDocument::createElement before loadHTMLFile creates 2 DOMDocuments.
Using DomDocument::createDocumentFragment acts the same and creates it's own DOM.
If you would like to keep your code the same and create two DomDocuments then you should use DomDocument::importNode, an example of this would be:
$dom = new DOMDocument();
$div = $dom->createElement("div");
$dom->loadHTMLFile("assets/dom_document-form.html");
$node = $dom->importNode($div);
$form = $dom->getElementsByTagName("form")->item(0);
$form->appendChild($node);
echo $dom->saveHTML();
Hello I have an api response in xml format with a series of items such as this:
<item>
<title>blah balh</title>
<pubDate>Tue, 20 Oct 2009 </pubDate>
<media:file date="today" data="example text string"/>
</item>
I want to use DOMDocument to get the attribute "data" from the tag "media:file". My attempt below doesn't work:
$xmldoc = new DOMDocument();
$xmldoc->load('api response address');
foreach ($xmldoc->getElementsByTagName('item') as $feeditem) {
$nodes = $feeditem->getElementsByTagName('media:file');
$linkthumb = $nodes->item(0)->getAttribute('data');
}
What am I doing wrong? Please help.
EDIT: I can't leave comments for some reason Mark. I get the error
Call to a member function getAttribute() on a non-object
when I run my code. I have also tried
$nodes = $feeditem->getElementsByTagNameNS('uri','file');
$linkthumb = $nodes->item(0)->getAttribute('data');
where uri is the uri relating to the media name space(NS) but again the same problem.
Note that the media element is of the form not I think this is part of the problem, as I generally have no issue parsing for attibutes.
The example you provided should not generate an error. I tested it and $linkthumb contained the string "example text string" as expected
Ensure the media namespace is defined in the returned XML otherwise DOMDocument will error out.
If you are getting a specific error, please edit your post to include it
Edit:
Try the following code:
$xmldoc = new DOMDocument();
$xmldoc->load('api response address');
foreach ($xmldoc->getElementsByTagName('item') as $feeditem) {
$nodes = $feeditem->getElementsByTagName('file');
$linkthumb = $nodes->item(0)->getAttribute('data');
echo $linkthumb;
}
You may also want to look at SimpleXML and Xpath as it makes reading XML much easier than DOMDocument.
Alternatively,
$DOMNode -> attributes -> getNamedItem( 'MyAttribute' ) -> value;