MalcolmInTheCenter
MalcolmInTheCenter

Reputation: 1605

PHP: How do I traverse through XML looking for a node?

I'm trying to traverse through XML looking for a specific node and then modify its value. I want to find <identifier_value> How can I do this? The xml below would be a string.

 <?xml version="1.0"?>
 <?xml-stylesheet href="catalog.xsl" type="text/xsl"?>
 <!DOCTYPE catalog SYSTEM "catalog.dtd">
 <catalog>
    <product description="Cardigan Sweater" product_image="cardigan.jpg">
       <catalog_item gender="Men's">
          <item_number>QWZ5671</item_number>
          <price>39.95</price>
          <size description="Medium">
             <color_swatch image="red_cardigan.jpg">Red</color_swatch>
             <color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>
          </size>
          <size description="Large">
             <color_swatch image="red_cardigan.jpg">Red</color_swatch>
             <color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>
          </size>
       </catalog_item>
       <catalog_item gender="Women's">
          <item_number>RRX9856</item_number>
          <price>42.50</price>
          <size description="Small">
             <color_swatch image="red_cardigan.jpg">Red</color_swatch>
             <color_swatch image="navy_cardigan.jpg">Navy</color_swatch>
             <color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>
          </size>
          <size description="Medium">
             <color_swatch image="red_cardigan.jpg">Red</color_swatch>
             <color_swatch image="navy_cardigan.jpg">Navy</color_swatch>
             <color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>
             <color_swatch image="black_cardigan.jpg">Black</color_swatch>
            <identifiers>
                <identifier>
                    <identifier_type>Test</identifier_type>
                    <identifier_value>000000001</identifier_value>
                </identifier>
            </identifiers>
          </size>
          <size description="Large">
             <color_swatch image="navy_cardigan.jpg">Navy</color_swatch>
             <color_swatch image="black_cardigan.jpg">Black</color_swatch>
          </size>
          <size description="Extra Large">
             <color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>
             <color_swatch image="black_cardigan.jpg">Black</color_swatch>
          </size>
       </catalog_item>
    </product>
 </catalog>

Upvotes: 0

Views: 45

Answers (2)

ThW
ThW

Reputation: 19492

PHPs DOM extension supports full Xpath 1.0 expressions.

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMxpath($document);


// fetch and modify identifier_value node 
$expression = '(//catalog_item//identifiers/identifier/identifier_value[.="000000001"])[1]';
foreach ($xpath->evaluate($expression) as $identifierValueNode) {
    $identifierValueNode->textContent = '000000042';

    // dump to validate
    var_dump($document->saveXML($identifierValueNode));
}

Output:

string(46) "<identifier_value>000000042</identifier_value>"

DOMXpath::evaluate() can not just return node list, but scalar values:

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMxpath($document);

// get the first catalog item with the specified identifier
$expression = '(//catalog_item[.//identifiers/identifier/identifier_value="000000001"])[1]';
foreach ($xpath->evaluate($expression) as $itemNode) {
    // read some scalar values 
    var_dump(
        $xpath->evaluate('string(item_number)', $itemNode),
        $xpath->evaluate('number(price)', $itemNode)
    );
}

Output:

string(7) "RRX9856"
float(42.5)

Upvotes: 0

PaulProgrammer
PaulProgrammer

Reputation: 17630

PHP has several plugins for working with XML. I would start with one of these. One might be the SimpleXMLElement::xpath method.

From https://www.php.net/manual/en/simplexmlelement.xpath.php

$xml = new SimpleXMLElement($xmlstring);
$result = $xml->xpath('//identifier_value[text()="value_to_find"]');
// do something with $result, perhaps modifying the value or formatting etc.

If you're taking that entire catalog (or even a portion of it) to render to a web page, you might want to consider xslt templates so that you don't have to parse the XML manually.

Upvotes: 1

Related Questions