Blog de programación, errores, soluciones

Chose Language:
Author: Admin/Publisher |not checked

PHP-DOM La clase DOMDocument

Este es una publicación temprana o early release, por favor sea paciente el tema se ira completando a lo largo del tiempo. Tenga en cuenta que el tema es demasiado largo como para crearlo rapidamente y es conveniente hacerlo de esta manera.

Tal como dijimos en manipulando el DOM la clase DOMDocument representará un documento HTML o XML y sirve como raíz del documento.

Para empezar a trabajar con el DOM con PHP deberás crear un nuevo objeto DOMDocument.

El siguiente código fue sacado de php.net este muestra las propiedades y métodos de DomDocument

class DOMDocument extends DOMNode {
/* Propiedades */
readonly public string $actualEncoding;
readonly public DOMConfiguration $config;
readonly public DOMDocumentType $doctype;
readonly public DOMElement $documentElement;
public string $documentURI;
public string $encoding;
public bool $formatOutput;
readonly public DOMImplementation $implementation;
public bool $preserveWhiteSpace = true;
public bool $recover;
public bool $resolveExternals;
public bool $standalone;
public bool $strictErrorChecking = true;
public bool $substituteEntities;
public bool $validateOnParse = false;
public string $version;
readonly public string $xmlEncoding;
public bool $xmlStandalone;
public string $xmlVersion;
/* Métodos */
public __construct(string $version = ?, string $encoding = ?)
public createAttribute(string $name): DOMAttr
public createAttributeNS(string $namespaceURI, string $qualifiedName): DOMAttr
public createCDATASection(string $data): DOMCDATASection
public createComment(string $data): DOMComment
public createDocumentFragment(): DOMDocumentFragment
public createElement(string $name, string $value = ?): DOMElement
public createElementNS(string $namespaceURI, string $qualifiedName, string $value = ?): DOMElement
public createEntityReference(string $name): DOMEntityReference
public createProcessingInstruction(string $target, string $data = ?): DOMProcessingInstruction
public createTextNode(string $content): DOMText
public getElementById(string $elementId): DOMElement
public getElementsByTagName(string $name): DOMNodeList
public getElementsByTagNameNS(string $namespaceURI, string $localName): DOMNodeList
public importNode(DOMNode $importedNode, bool $deep = false): DOMNode
public load(string $filename, int $options = 0): mixed
public loadHTML(string $source, int $options = 0): bool
public loadHTMLFile(string $filename, int $options = 0): bool
public loadXML(string $source, int $options = 0): mixed
public normalizeDocument(): void
public registerNodeClass(string $baseclass, string $extendedclass): bool
public relaxNGValidate(string $filename): bool
public relaxNGValidateSource(string $source): bool
public save(string $filename, int $options = 0): int
public saveHTML(DOMNode $node = NULL): string
public saveHTMLFile(string $filename): int
public saveXML(DOMNode $node = ?, int $options = 0): string
public schemaValidate(string $filename, int $flags = 0): bool
public schemaValidateSource(string $source, int $flags = ?): bool
public validate(): bool
public xinclude(int $options = 0): int

/* Métodos heredados */
public DOMNode::appendChild(DOMNode $newnode): DOMNode
public DOMNode::C14N(
    bool $exclusive = ?,
    bool $with_comments = ?,
    array $xpath = ?,
    array $ns_prefixes = ?
): string
public DOMNode::C14NFile(
    string $uri,
    bool $exclusive = false,
    bool $with_comments = false,
    array $xpath = ?,
    array $ns_prefixes = ?
): int
public DOMNode::cloneNode(bool $deep = ?): DOMNode
public DOMNode::getLineNo(): int
public DOMNode::getNodePath(): string
public DOMNode::hasAttributes(): bool
public DOMNode::hasChildNodes(): bool
public DOMNode::insertBefore(DOMNode $newnode, DOMNode $refnode = ?): DOMNode
public DOMNode::isDefaultNamespace(string $namespaceURI): bool
public DOMNode::isSameNode(DOMNode $node): bool
public DOMNode::isSupported(string $feature, string $version): bool
public DOMNode::lookupNamespaceUri(string $prefix): string
public DOMNode::lookupPrefix(string $namespaceURI): string
public DOMNode::normalize(): void
public DOMNode::removeChild(DOMNode $oldnode): DOMNode
public DOMNode::replaceChild(DOMNode $newnode, DOMNode $oldnode): DOMNode
}

Métodos

A continuación una tabla de los métodos de la clase DomDocument

MetodosAtributosretorno
__construct$version, $encodingvoid
createAttribute$nameDOMAttr(obj)
createAttributeNS$namespaceURI, $qualifiedNameDOMAttr(obj)
createCDATASection$dataDOMCDATASection
createComment$dataDOMComment
createDocumentFragmentDOMDocumentFragment
createElement$name,$valueDOMElement
createElementNS$namespaceURI,$qualifiedName,$valueDOMElement
createEntityReference$nameDOMEntityReference
createProcessingInstruction$target,$dataDOMProcessingInstruction
createTextNode$contentDOMText
getElementById$elementIdDOMElement
getElementsByTagName$nameDOMNodeList
getElementByTagNameNS$namespaceURI,$localNameDOMNodeList
importNode$importedNode, $deepDOMNode
load$filename,$optionsmixed
loadHTML$source, $optionsbool
loadHTMLFile$filename, $optionsbool
loadXML$source,$optionsmixed
normalizeDocumentvoid
registerNodeClass$baseclass, $extendedclassbool
relaxNGValidate$filenamebool
relaxNGValidateSource$sourcebool
save$filename,$optionsint
saveHTML$nodestring
saveHTMLFile$filenameint
saveXML$node, $optionstring
schemaValidate$filename,$flagbool
schemaValidateSource$source,$flagbool
validatebool
xinclude$optionsint

Recordemos que estaremos trabajando con XML, y por tanto los métodos que hablan sobre namespace están referendo a los namespace en XML no en PHP.

Puedes entrar en el siguiente link de Namespaces en XML para mas info sobre el tema.

createAttribute

Crea un atributo. Para ver como utilizar este método crearemos un objeto DOMDocument $objDom

<?php
$objDom = new DOMDocument();
$main = $objDom->createElement("main");
$text = $objDom->createElement("p","this is an example of blastcoding.com, domatributte");
$attribute = $objDom->createAttribute("id");
$attribute->value ="main";
$objDom->appendChild($main);
$main->appendChild($attribute);
$main->appendChild($text);
//thanks to prefer us, Blastcoding.com

echo $objDom->saveHTML();

Este ejemplo puede parecerte que tiene mucho código pero no en realidad tuve que crear un elemento al cual aplicarle el atributo ademas hay algo que tengo que recalcar aquí.

para poder mostrar el html debes ligar el elemento a el objeto Dom.

$objDom->appendChild($main);

Ademas de esto esta linea puedes tenerla después de crear el elemento, de ahí puede estar donde quieras.

Si quieres comparar el DOMDocument con algo de la vida real puedes compararlo con un juego de legos cuando creo el objeto dom tengo la caja de legos y con ellos los conecto como desee hacerlo.

createAttributeNS

Crea un nuevo nodo atributo con un namespace asociado. en pocas palabras crea un atributo con xmlns o xmlns:name

su sintaxis seria:

 public DOMDocument::createAttributeNS(string $namespaceURI, string $qualifiedName): DOMAttr

que sea un atributo el retorno es entendible, veamos mas en concreto lo que podremos hacer con este método.

Tengamos en cuenta este ejemplo:

<book xmlns:bookinfo="urn:isbn:9780553382563">
  <title>I Robot</title>
  <author>Isac Asimov</author>
</book>

¿Como puedo crear esto a partir de PHP?

Primero hagamos que imprima el xml sin nuestro namespace. El siguiente codigo deberia ser suficiente:

<?php
$objDom2 = new DOMDocument();
$book = $objDom2->createElement("book");
$title = $objDom2->createElement("title","I Robot");
$author = $objDom2->createElement("author","Isac Asimov");
$objDom2->appendChild($book);
$book->appendChild($title);
$book->appendChild($author);
header('Content-type: text/xml');
echo $objDom2->saveXML();
?>
<book>
<title>I Robot</title>
<author>Isac Asimov</author>
</book>

vamos a agregar nuestro namespace

<?php
$objDom2 = new DOMDocument("1.0");
$book = $objDom2->createElement("book");
$title = $objDom2->createElement("title","I Robot");
$author = $objDom2->createElement("author","Isac Asimov");
$objDom2->appendChild($book);
$nsatributte = $objDom2->createAttributeNS("http://blastcoding.com","web");


$book->appendChild($nsatributte);
$book->appendChild($title);
$book->appendChild($author);
header('Content-type: text/xml');
echo $objDom2->saveXML();
?>
<book xmlns="http://blastcoding.com" web="">
<title>I Robot</title>
<author>Isac Asimov</author>
</book>

Vea que hemos puesto por encima el appendChild de $book de nuestro atributo, esto es porque necesitas un elemento que sea raíz.

Recomendado

En caso de que estés muy interesado en XML dejo este libro por si lo deseas comprar en Amazon, el cual posee mucha mas información de la que pueda brindar el blog. Los temas dados en el blog son temas concretos y que tienen que ver con PHP.

createCDATASection

Crea un nodo que es una sección CDATA(XML), en caso de no tener idea de lo que es ver seccion-cdata-en-xml.

Sintaxis
 public DOMDocument::createCDATASection(string $data): DOMCdataSection|false

Este método devuelve un objeto DOMCdataSection en caso de haber un error devolverá false.

Veamos un ejemplo:

<?php
$objDom = new DOMDocument();
$main = $objDom->createElement("main");
$cdata = $objDom->createCDATASection("<code>//here goes the code</code>");
$objDom->appendChild($main);
$main->appendChild($cdata);
header('Content-type: text/xml');
echo $objDom->saveXML();

createComment

El método createComment crea un nodo comentario DOMComment(HTML o XML commnet).

public DOMDocument::createComment(string $data): DOMComment

Estilo de comentario

hagamos un ejemplo:

<?php
$objDom = new DOMDocument();
$main = $objDom->createElement("main");
$comment = $objDom->createComment("this is a comment");
$objDom->appendChild($main);
$main->appendChild($comment);
header('Content-type: text/xml');
echo $objDom->saveXML();

createDocumentFragment

La primera vez que vi createDocumentFragment me pregunte que hace acaso cada nodo no hace lo mismo que esta funcion, pues no resulta que la función createDocumentFragment crea un objeto DOMDocumentFragment el cual hereda de DOMNode pero a su vez agrega un metodo el cual es appendXML().

Este método puede sernos realmente util, imagina estar utilizando una api de un tercero que te devuelve un XML y nuestro programa solo tiene que agregar algo y volver a mandar como un XML su contenido.

Sintaxis
public DOMDocument::createDocumentFragment(): DOMDocumentFragment

en caso de fallar devolvera false

¿Como podriamos simular una pagina que nos devuelve un XML con lo dado hasta ahora?

Lo único que se me ocurre es utilizar file_get_contents y así simular la devolución que hace una API claro que lo que haremos sera un XML para simular esto. Utilizemos el ejemplo del CDATA.

an XML file(cdata.xml)
<?xml version="1.0"?>
<datainside>
<greeting>Hello, world!</greeting>
<data>
<![CDATA[
<greeting>Hello, world!</greeting>
]]>
</data>
</datainside>

veamos un ejemplo simple de como crearlo:

<?php
function cleanXML($file){
    $xmlpos = strpos($file,"?>");
    return substr($file, $xmlpos+2,strlen($file));
}
$objDom = new DOMDocument("1.0");
$fragment =$objDom->createDocumentFragment();
$XMLfile = file_get_contents("cdata.xml");
$fragment->appendXML(cleanXML($XMLfile));
$objDom->appendChild($fragment);
header('Content-type: text/xml');
echo $objDom->saveXML();

Lo que hace la función es claro y no creo que necesite explicación, aunque de todos modos explicaremos lo que hace y es limpiar el la definición de la presentación de XML.

createElement

Crea un elemento, sus parametros son $name y $value siendo value un parámetro opcional.

Sintaxis
public DOMDocument::createElement(string $name, string $value = ?): DOMElement

Creo que no necesitaríamos mas ejemplos sobre este método ya que lo venimos usando desde el inicio de la pagina, de todos modos daremos el ejemplo mas simple que se pueda hacer con este método.

<?php
$objDom = new DOMDocument();
$main = $objDom->createElement("main");
$text = $objDom->createElement("p","this is an example of blastcoding.com createElement");
$objDom->appendChild($main);
$main->appendChild($text);
echo $objDom->saveHTML();

createElementNS

crea un elemento vinculado a un namespace, ya hablamos de xmlns antes en createAtributteNS tambien puedes chequear la pagina de namespaces en XML para tener mas claro de lo que se esta hablando.

Sintaxis
public DOMDocument::createElementNS(?string $namespace, string $qualifiedName, string $value = ""): DOMElement|false

vamos rápidamente a crear un elemento de este estilo:

<?php
$objDom = new DOMDocument();
$main = $objDom->createElementNS("blastcoding.com/info","info:main","root element");//tenga en cuenta que blastcoding.com/info no existe solo lo estoy usando como parte logica
$text = $objDom->createElementNS("blastcoding.com/info","info:p","this is an example of blastcoding.com createElementNS");
$objDom->appendChild($main);
$main->appendChild($text);
header('Content-type: text/xml');
echo $objDom->saveXML();
<info:main xmlns:info="blastcoding.com/info">
root element
<info:p>this is an example of blastcoding.com createElement </info:p>
</info:main>

Lo que acabo de hacer anteriormente es un scoped namespace.

createEntityReference

Crea una entity Reference como un nodo. ¿Que es la entidad a la que se refiere? son grupos de letras los cuales representaran un symbolo especial. Estos son los simbolos que deberia poder reperesentar https://dev.w3.org/html5/html-author/charref.

Sintaxis
 public DOMDocument::createEntityReference(string $name): DOMEntityReference

La variable $name debe ser escrita sin el simbolo & inicial y sin el simbolo ; final.

<?php
$dom=new DOMDocument("1.0","UTF-8");
$example=$dom->createElement("example","who are you");
$entity=$dom->createEntityReference("quest");
$example->appendChild($entity);
$dom->appendChild($example);
echo $dom->saveXML();
who are you?

Recuerde que lo que pide createEntityReference es un entity name un valor numerico tanto decimal como hexa no funcionara

createProcessingInstruction

Las instrucciones de proceso o procesing instructions en ingles(PI) nos permite tener en el documento instrucciones para aplicaciones.

Con createPrcesingInstruction crearemos un nodo de PI

Las instrucciones de proceso en si no son muy utilizadas ecepto cuando se agrega estilo a nuestro XML, igual tenga en cuenta que hay otras formas de agregar estilo a nuestro XML. Una de estas formas es explicada por Bert Bos en https://www.w3.org/Style/styling-XML.en.html

Estilo CSS en XML
<?xml-stylesheet href="style.css" type="text/css"?>

Tambien puedes usar estilos XLS

<?xml-stylesheet type="text/xsl" href="myxls.xsl"?> 

¿Pero me estas hablando de XML como lo hago atravez de PHP?

Si antes de utilizar una funcion tenmos que saber que accion realiza. No tiene sentido decir esto se hace asi y ya.

Ahora si vamos a PHP

Sintaxis
 public DOMDocument::createProcessingInstruction(string $target, string $data = ""): DOMProcessingInstruction|false

$data sera el contenido de la instruccion y $target sera el objetivo de la instruccion

Hagamos un ejemplo pero primero necesitaremos un archivo style.css:

book{
    display: block;
    padding: 5px;
    background-color:aquamarine;
}
title,author{
    display: block;
    max-width:300px;
    padding: 5px;
    background-color:rebeccapurple;
    border:1px solid white;
    color:white;
}

Ahora tenemos que hacer nuestro archivo php.

$objDom2 = new DOMDocument();
$css = $objDom2->createProcessingInstruction('xml-stylesheet', 'type="text/css" href="style.css"');
$book = $objDom2->createElement("book");
$title = $objDom2->createElement("title","I Robot");
$author = $objDom2->createElement("author","Isac Asimov");
$objDom2->appendChild($css);
$objDom2->appendChild($book);
$book->appendChild($title);
$book->appendChild($author);
header('Content-type: text/xml');
echo $objDom2->saveXML();
?>

createTextNode

Crea un Nodo de texto

Sintaxis
public DOMDocument::createTextNode(string $content): DOMText

Ejemplo:

<?php
$objDom = new DOMDocument();
$main = $objDom->createElement("main");
$text = $objDom->createElement("p","this is an example of blastcoding.com createElement");
$extraText = $objDom->createTextNode("extra content here");
$objDom->appendChild($main);
$main->appendChild($text);
$main->appendChild($extraText);
header('Content-type: text/xml');
echo $objDom->saveXML();
<main>
<p>this is an example of blastcoding.com createElement</p>
extra content here
</main>

getElementById

Este metodo es similar a getElementById de javascript, de echo realiza la misma accion, obtiene un elemento perteneciente a el objeto DOMDocument en el que lo estamos llamando.

Sintaxis
 public DOMDocument::getElementById(string $elementId): ?DOMElement

En la sintaxis puede ver que nos puede devolver un Objeto DOMElement o null.

si el html no posee la declaracion de doctype este metodo devolvera null

Ahora hagamos un ejemplo de como usar getElementById:

<?php
$objDom = new DOMDocument('1.0', 'UTF-8');
$HTML = <<<HTML
<!DOCTYPE html>
<html>
    <head>
        <title>example of get element</title>
</head>
<body>
<main id="xmain">
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</main>
<footer>
    Made by Blastcoding.com
</footer>
</body>
</html>
HTML;
libxml_use_internal_errors(true);
$objDom->loadHTML($HTML);
$idMainElement = $objDom->getElementById('xmain');
if($idMainElement != null){
    echo $idMainElement->nodeValue;
}else{
    echo "couldn't get element";
}

getElementsByTagName

El método getElementsByTagName también tiene su similar en JavaScript, este obtiene el elemento por su nombre de etiqueta(tag).

Note que este método obtendrá todos los elemento con esa etiqueta, vea el siguiente ejemplo:

<?php
$objDom = new DOMDocument('1.0', 'UTF-8');
$HTML = <<<HTML
<!DOCTYPE html>
<html>
    <head>
        <title>example of get element</title>
</head>
<body>
<main id="xmain">
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</main>
<footer>
    Made by Blastcoding.com
</footer>
</body>
</html>
HTML;
libxml_use_internal_errors(true);
$objDom->loadHTML($HTML);
$elements = $objDom->getElementsByTagName('main');
if($elements != null){
    echo $elements[0]->nodeValue;
}else{
    echo "couldn't get elements";
}

getElementByTagNameNS

Comming Soon

Under research, or under creation

importNode

Importa un nodo hacia el documento actual.

 public DOMDocument::importNode(DOMNode $importedNode, bool $deep = false): DOMNode

En este ejemplo tomamos lo antes dado en getElementById y lo modificamos para importar un elemento de un DOMDocument a otro.

<?php
$objDom = new DOMDocument('1.0', 'UTF-8');
$otherDom = new DOMDocument();
$HTML = <<<HTML
<!DOCTYPE html>
<html>
    <head>
        <title>example of get element</title>
</head>
<body>
<main id="xmain">
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</main>
<footer>
    Made by Blastcoding.com
</footer>
</body>
</html>
HTML;

libxml_use_internal_errors(true);
$objDom->loadHTML($HTML);
$idMainElement = $objDom->getElementById('xmain');
if($idMainElement != null){
    $node = $otherDom->importNode($idMainElement, true);
    $otherDom->appendChild($node);
    header('Content-type: text/xml');
    echo $otherDom->saveXML();
}else{
    echo "couldn't get element";
}

load

Comming Soon

Under research, or under creation

loadHTML

Comming Soon

Under research, or under creation

loadHTMLFile

Comming Soon

Under research, or under creation

loadXML

Comming Soon

Under research, or under creation

normalizeDocument

Comming Soon

Under research, or under creation

registerNodeClass

Comming Soon

Under research, or under creation

relaxNGValidate

Comming Soon

Under research, or under creation

relaxNGValidateSource

Comming Soon

Under research, or under creation

save

Comming Soon

Under research, or under creation

saveHTML

Comming Soon

Under research, or under creation

saveHTMLFile

Comming Soon

Under research, or under creation

saveXML

Comming Soon

Under research, or under creation

schemaValidate

Comming Soon

Under research, or under creation

schemaValidateSource

Comming Soon

Under research, or under creation

validate

Comming Soon

Under research, or under creation

xinclude

Comming Soon

Under research, or under creation

Category: php
Something wrong? If you found an error or mistake in the content you can contact me on Twitter | @luisg2249_luis.
Last 4 post in same category