How to extract DOM childNodes or rename an element without using iteration?

$xml = '<p><a>1</a><b><c>1</c></b></p>'; $dom = new DomDocument; $dom->loadXML($xml); $p = $dom->childNodes->item(0); echo $dom->saveXML($p); 

above will bring back

 <p> <a>1</a> <b><c>1</c></b> </p> 

suppose you want to replace p node / eleemnt with new_p What is the ideal way besides the loop as shown below? (below doable)

 $fragment = ''; foreach ($p->childNodes as $a) { $fragment .= $dom->saveXML($a); } $new_doc = new DomDocument; $new_doc->loadXML('<new_node/>'); $f = $new_doc->createDocumentFragment(); $f->appendXML($fragment); $new_doc->documentElement->appendChild($f); echo $new_doc->saveXML(); 

Expected results

 <new_node><a>1</a><b><c>1</c></b></new_node> 
+4
source share
3 answers

As Mark already pointed out, XML manipulation is easiest with XSLT. And you do not need to write any cycles, thinking is done using the XSLT processor of your choice.

Simple instruction with XSLT

Here's what XSLT might look like (Google for "XSLT Transformation Identity" for some tutorials).

The basics are simple: this type of XSLT transform copies everything as is, unless there is a specific rule (pattern matching in XSLT) that indicates an exception (in this case, for <p> elements). Note: It doesn’t matter how deep your p-tags are, which makes it ideal for XML conversion.

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- identity transform --> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- rename "p" with "new_p", copy everything inside p --> <xsl:template match="p"> <new_p> <xsl:apply-templates select="@* | node()"/> </new_p> </xsl:template> </xsl:stylesheet> 

Call XSLT from PHP

This is relatively simple since PHP has a built-in module for XSL. Here is how you can do it ( here is more information ):

 // create an XSLT processor and load the stylesheet as a DOM $xproc = new XsltProcessor(); $xslt = new DomDocument; $xslt->load('yourstylesheet.xslt'); // this contains the code from above $xproc->importStylesheet($xslt); // your DOM or the source XML (copied from your question) $xml = '<p><a>1</a><b><c>1</c></b></p>'; $dom = new DomDocument; $dom->loadXML($xml); // do the transformation if ($xml_output = $xproc->transformToXML($dom)) { echo $xml_output; } else { trigger_error('Oops, XSLT transformation failed!', E_USER_ERROR); } 

Exit as expected (optional indentation can be set using <xsl:output indent="yes"/> :

 <new_p> <a>1</a> <b><c>1</c></b> </new_p> 

As you can see: no loops or iterations;)

PS: XSLT is a widespread and stable standard. You do not have to worry about properly escaping, analyzing problems with partitions or CDATA entities, as XSLT ensures that the output is valid XML. This saves a ton of headaches rather than doing it manually.

+3
source

Is XSLT suitable for this kind of operation?

How to rename elements with XSLT

+2
source

Although the loop is an obvious solution, some situations may interfere with this or make it inapplicable; although I don’t know one thing. Alternatively, this can be achieved by manipulating the string, input XML string, or output XML from the $new_doc->saveXML() method, depending on what you can use. I would go with str_ireplace or regular expressions if the tags contain attributes, in particular preg_replace with the i flag for case insensitive search. I could give examples this way if you are interested in this technique.

-3
source

Source: https://habr.com/ru/post/1340677/


All Articles