php, how to clone DOMElement? - php

Official documentation says that DOMElement has inherited method cloneNode http://php.net/manual/en/class.domelement.php . If i try to clone, it does not work. How to copy element from one DOMDocument to another? Namely, i have misplaced head, thus i have somehow to copy head and body, and than to echo them in right order.
ob_start();
$viewData = $this->data;
include_once( $this->viewTemplPath.$this->file );
$buffer = ob_get_clean();
$doc = new \DOMDocument();
$doc->loadHTML($buffer);
$head = $doc->getElementsByTagName('head')->item(0);
print_r('<br><br> 184 view.php head='); var_dump($head);
$body = $doc->getElementsByTagName('body')->item(0);
print_r('<br><br> 188 view.php body='); var_dump($body);
$docNew = new \DOMDocument();
$headNew = $head->cloneNone(true); // Fatal error: Call to undefined method DOMElement::cloneNone()
$docNew->appendChild($headNew);
$bodyNew = $body->cloneNone(true); // Fatal error: Call to undefined method DOMElement::cloneNone()
$docNew->appendChild($bodyNew);
echo $docNew->saveHTML();

In order to clone the Element, the solution is to import the Element i want to clone to the Document, and than add it as a child : http://php.net/manual/en/domdocument.importnode.php
This does not through errors, and echoes the new document.
But this does not resolve the problem with misplaced head.
ob_start();
$viewData = $this->data;
include_once( $this->viewTemplPath.$this->file );
$buffer = ob_get_clean();
$doc = new \DOMDocument();
$doc->loadHTML($buffer);
$head = $doc->getElementsByTagName('head')->item(0);
$body = $doc->getElementsByTagName('body')->item(0);
$docNew = new \DOMDocument();
$headNew = $docNew->importNode($head, true);
$docNew->appendChild($headNew);
$bodyNew = $docNew->importNode($body, true);
$docNew->appendChild($bodyNew);
echo $docNew->saveHTML();

You have typo mistake,
you wrote it CloneNone(true),
it should be cloneNode(true)

Related

Create a WSDL with REST

I have a several problems to moment to create a WSDL with REST in PHP. I read a little bit about this, supposedly REST use WADL. I need a library or framework that generated a WADL or type WSDL of my code PHP (class, methods, vars).
Thanks a lot!
I created a simulation with php but this no get the return vars
... Class
... Methods
... Vars
if(isset($_GET['wadl'])):
header('Content-Type: text/xml');
$foo = new proveedores();
$get_class = get_class($foo);
// create the new XML document
$dom = new DOMDocument('1.0', 'iso-8859-1');
// create the root element
$list_of_teams = $dom->createElement($get_class);
$dom->appendChild($list_of_teams);
$class = new ReflectionClass($get_class);
$methods = $class->getMethods();
foreach ($methods as $m) {
$method = $class->getMethod($m->name);
// create the first element
$team = $dom->createElement($m->name);
$list_of_teams->appendChild($team);
$parameters = $method -> getParameters();
if(!empty($parameters)):
foreach ($parameters as $p) {
$name = $team->appendChild($dom->createElement('parameters'));
$name->appendChild($dom->createTextNode($p -> name));
}
endif;
}
print $xml_result = $dom->saveXML();
endif;

PHP creating multiple DOMDocuments in a loop issue

I have a list of items to be added to the end of a base url and am trying to retrieve the html from each of these generated url's in a loop. However, I am encountering an error and i've really been struggling to fix it!
current code:
($items is just an array of strings)
$output = "";
foreach($items as $item) {
$url = $baseUrl . $item;
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTMLFile($url);
$output = $output . json_encode($dom->saveHTML());
}
echo $output;
Can anyone tell me why I can't load multiple HTML documents like this?
Annoyingly i'm not getting any PHP error logs and the ajax xhr text is not providing any useful info, it's just returning a section of the first html page loaded as the 'error' (it seems to be able to load the first item in the array but then fails)
You were almost there. This way it should do the trick:
$output = "";
foreach($items as $item) {
$url = $baseUrl . $item;
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTMLFile($url);
$output .= json_encode($dom->saveHTML(),JSON_ERROR_UTF8);
}
echo $output;

Interpret string as HTML in PHP

i am working on PHP, and i've only just begun, so i would like to ask some advice on something i can't quite seem to find online.
I have a PHP-file that gets 2 strings: A name and a lot of HTML-text.
$name = $_POST['name'];
$content = $_POST['content'];
Now i want to use those 2 to create a new HTML file and save it. So far i've managed to make it save a new HTML file and use the name as the <title> tag. Now what i want is to do is replace the (currently empty) body with my HTML string, interpreted as HTML.
This builds my body tag:
$body = $doc->createElement('body');
$body = $root->appendChild($body);
Now i found 2 ways to do this, and both don't work:
Solution 1:
$content = $doc->createTextNode($content);
$content = $body->appendChild($content);
This inserts my HTML into my body, but it parses literally as '<div id="lala">content</div>'. So this isn't what i want.
Solution 2:
$content = $doc->loadHTML($content);
This actually makes the html load as HTML, but now it replaces my entire HTML and things like adding css and js to the head will now actually go UNDER the new body, instead of in the head. As such:
$link_1 = $doc->createElement('link');
$link_1->setAttribute('rel','stylesheet');
$link_1->setAttribute('href','css/mystylesheet.min.css');
$link_1 = $head->appendChild($link_1);
So basically i want to both interpret my string as HTML, AND make it load in the correct place. I've tried to change it to $body->loadHTML($content), but this gives me an internal error.
Does anyone know the PHP-method i'm looking for? Thanks!
This will work. Let me know if you need explanation :)
<?php
ini_set( 'display_errors', 1 );
ini_set( 'error_reporting', E_ALL );
$dom = new DOMDocument( '1.0' );
$dom->formatOutput = true;
$dom->preserveWhiteSpace = true;
// test values
$name = 'Test';
$content = '<div onclick="alert(\'Hello!\');">Test div</div>';
// create <html>, <head>, <title> and <body> tags
$html = $dom->createElement( 'html' );
$head = $dom->createElement( 'head' );
$title = $dom->createElement( 'title' );
$body = $dom->createElement( 'body' );
// title text
$titleText = $dom->createTextNode( $name );
// import the text in a new dom
$dom1 = new DOMDocument( '1.0' );
$dom1->formatOutput = true;
$dom1->preserveWhiteSpace = true;
$bodyText = $dom1->loadHTML( $content );
$bodyText = $dom1->getElementsByTagName('body')->item(0);
// add them to the dom
$html = $dom->appendChild( $html );
$html->appendChild( $head );
$head->appendChild( $title );
$title->appendChild( $titleText );
$html->appendChild( $body );
$bodyT = $dom->importNode( $bodyText, true );
$body->appendChild( $bodyT );
echo $dom->saveHTML();
?>
Hope this helps.
Of course, the text in createTextNode stands for plain text (vs. HTML).
Fatal error: Call to undefined method DOMElement::loadHTML()
Correct, loadHTML() belongs to DOMDocument, not DOMElement. In your case, the document is apparently $doc (not $body). So you need to call:
$doc->loadHTML()

xml generation from php if file doesnt exist

This code works if file is previously expisting but if file doesn't exist this code doesnt work.
$doc = new DOMDocument();
$doc->version = '1.0';
$doc->encoding = 'ISO-8859-1';
$response = $doc->createElement('response');
$doc->appendChild($response);
$response_type= $doc->createElement('response_type','Yes');
$response_id = $doc->createElement('response_id',$max_id_site);
$response->appendChild($response_type);
$response->appendChild($response_id);
$doc->formatOutput = true;
echo $doc->saveXML();
$doc->save('$filename_xml');
updated code
$doc = new DOMDocument();
$doc->version = '1.0';
$doc->encoding = 'ISO-8859-1';
$response = $doc->createElement('response');
$doc->appendChild($response);
$response_type= $doc->createElement('response_type','Yes');
$response_id = $doc->createElement('response_id',$max_id_site);
$response->appendChild($response_type);
$response->appendChild($response_id);
$doc->formatOutput = true;
echo $doc->saveXML();
if (! is_file($filename_xml)) {
touch($filename_xml) or trigger_error("Can't Create File");
$doc->save($filename_xml);
}
You can replace
$doc->save('$filename_xml');
with
if (! is_file($filename_xml)) {
touch($filename_xml) or trigger_error("Can't Create File");
$doc->save($filename_xml);
}
Use file_exists() to check if file is already there.
Replace last line:
$doc->save('$filename_xml');
with
if( file_exists( $filename_xml ) == false ) {
$doc->save( $filename_xml );
}
In general you should not even generate the xml if file is there.
BTW: Putting $filename_xml) in "`" is wrong.

Prevent save() from overwriting dtd in an xml file

I'm writing a script that adds nodes to an xml file. In addition to this I have an external dtd I made to handle the organization to the file. However the script I wrote keeps overwriting the dtd in the empty xml file when it's done appending nodes. How can I stop this from happening?
Code:
<?php
/*Dom vars*/
$dom = new DOMDocument("1.0", "UTF-8");
$previous_value = libxml_use_internal_errors(TRUE);
$dom->load('post.xml');
libxml_clear_errors();
libxml_use_internal_errors($previous_value);
$dom->formatOutput = true;
$entry = $dom->getElementsByTagName('entry');
$date = $dom->getElementsByTagName('date');
$para = $dom->getElementsByTagname('para');
$link = $dom->getElementsByTagName('link');
/* Dem POST vars used by dat Ajax mah ziggen, yeah boi*/
if (isset($_POST['Text'])){
$text = trim($_POST['Text']);
}
/*
function post(){
global $dom, $entry, $date, $para, $link,
$home, $about, $contact, $text;
*/
$entryC = $dom->createElement('entry');
$dateC = $dom->createElement('date', date("m d, y H:i:s")) ;
$entryC->appendChild($dateC);
$tab = "\n";
$frags = explode($tab, $text);
$i = count($frags);
$b = 0;
while($b < $i){
$paraC = $dom->createElement('para', $frags[$b]);
$entryC->appendChild($paraC);
$b++;
}
$linkC = $dom->createElement('link', rand(100000, 999999));
$entryC->appendChild($linkC);
$dom->appendChild($entryC);
$dom->save('post.xml');
/*}
post();
*/echo 1;
?>
It looks like in order to do this, you'd have to create a DOMDocumentType using
DOMImplementation::createDocumentType
then create an empty document using the DOMImplementation, and pass in the DOMDocumentType you just created, then import the document you loaded. This post: http://pointbeing.net/weblog/2009/03/adding-a-doctype-declaration-to-a-domdocument-in-php.html and the comments looked useful.
I'm guessing this is happening because after parsing/validation, the DTD isn't part of the DOM anymore, and PHP therefore isn't able to include it when the document is serialized.
Do you have to use a DTD? XML Schemas can be linked via attributes (and the link is therefore part of the DOM). Or there's RelaxNG, which can be linked via a processing instruction. DTDs have all this baggage that comes with them as a holdover from SGML. There are better alternatives.

Categories