Search code examples
phpxml

PHP XML Replace node value by text on existing XML file


Suppose I have a XML file with a structure unknown to me. But I know that somewhere in that xml structure, one node has a known value, for instance, {1} as in node->nodeValue="{1}".

How can I create another XML file, identical to the first one, but with that value {1} replaced with another value ('New value')?

Here's what I've tried, without sucess:

    $xmlfile=$this->xmlPath.'document1.xml';
    $xmlwfile=$this->xmlPath.'document2.xml';
    $this->xml = new XMLReader();
    $this->xml->open($xmlfile);

    $this->wxml = new DOMDocument();
    
    while($this->xml->read())
    {
        $node = $this->xml->expand();

        if($this->xml->nodeType == XMLReader::TEXT) 
        {
            if(str_contains($this->xml->value,"{1}"))
            {
                $node->nodeValue='New Value';
            }
        }
        
        $this->wxml->appendChild($this->wxml->importNode($node, true));            
    }
    
    $this->wxml->save($xmlwfile); 
    
    $this->xml->close();

Any thoughts? Thanks, Pedro


Solution

  • Here is XSLT based solution that is using a so called Identity Transform pattern.

    You just need to launch XSLT transformation in php.

    Input XML

    <?xml version="1.0"?>
    <root>
        <foo>whatever</foo>
        <moo>cow</moo>
    </root>
    

    XSLT

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" omit-xml-declaration="no"
                    encoding="UTF-8" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:param name="findme" select="'whatever'"/>
        <xsl:param name="replaceWith" select="'newvalue'"/>
    
        <!--Identity transform-->
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="foo[text()=$findme]">
            <xsl:copy>
                <xsl:value-of select="$replaceWith"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    Output XML

    <?xml version='1.0' encoding='UTF-8'?>
    <root>
      <foo>newvalue</foo>
      <moo>cow</moo>
    </root>