0

How can I find a node with a value of other node in the same level in XML? XML:

<config>
  <module>
    <idJS >001</idJS>
    <addressPLC>41000</addressPLC>
  </module>
  <module>
    <idJS >002</idJS>
    <addressPLC>42000</addressPLC>
  </module> 
</config>

PHP:

<?php
$doc = new DOMDocument();
$doc->load( 'file.xml' );
$config = $doc->getElementsByTagName( "module" );

$ids = $doc->getElementsByTagName('idJS');
foreach ($ids as $id) {
  if ($id->nodeValue == '001') {
      echo $addressPLC;
  }
}
?>

How get the nodeValue of "addressPLC" with "idJS"?

hsz
  • 148,279
  • 62
  • 259
  • 315
vicenrele
  • 971
  • 3
  • 19
  • 37

4 Answers4

0

To get addressPLC having idJS you can get parent and find elements in parent:

$addressPLC = $id->parentNode->getElementsByTagName("addressPLC");
echo $addressPLC->nodeValue;
hsz
  • 148,279
  • 62
  • 259
  • 315
  • I don't Know why I obtain this error: "Undefined property: DOMNodeList::$nodeValue" in the next line: echo $addressPLC->nodeValue; – vicenrele Jan 09 '13 at 14:29
0

There is no direct method in PHP to retrieve all the siblings to a given node. You need to select the parent element via $node->parentNode and then select the desired element starting from that parent element and using the methods you already know (e.g. getElementsByTagName()).

There is also a user comment in the DOM documentation over at php.net, which has an implementation to find any siblings to a given node: http://php.net/dom#60188

feeela
  • 29,399
  • 7
  • 59
  • 71
0

I think a preferable way to go is to iterate through the <module> nodes (instead of the idJS nodes) and retrieve both the idJS and addressPLC from that point.

It looks like there isn't an easy way to get a node's child elements by name, but you could add this convenience function (from here: PHP DOMElement::getElementsByTagName - Anyway to get just the immediate matching children?):

/**
 * Traverse an elements children and collect those nodes that
 * have the tagname specified in $tagName. Non-recursive
 *
 * @param DOMElement $element
 * @param string $tagName
 * @return array
 */
function getImmediateChildrenByTagName(DOMElement $element, $tagName)
{
    $result = array();
    foreach($element->childNodes as $child)
    {
        if($child instanceof DOMElement && $child->tagName == $tagName)
        {
            $result[] = $child;
        }
    }
    return $result;
}

Then you'd have:

foreach ($config as $module) {
  $idJS = getImmediateChildrenByTagName($module, "idJS")[0];
  if ($idJS->nodeValue == '001') {
      echo getImmediateChildrenByTagName($module, "addressPLC")[0]->nodeValue;
  }
}
Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • My mistake. That should have been $module inside the loop. – JLRishe Jan 09 '13 at 14:39
  • Thanks. One question: Why put "[0]" in the end of the called to getImmediateChildrenByTagName() function? – vicenrele Jan 09 '13 at 14:55
  • Because getImmediateChildrenByTagName returns an array of DOMElements. In XML, an element could have more than one child with the same name, though I'm assuming your XML will always have exactly one `` under each ``. – JLRishe Jan 09 '13 at 15:01
  • Ok. Yes, my XML has only one – vicenrele Jan 09 '13 at 15:08
0

You really should use xpath for that:

$xp = new DOMXpath($doc);
echo $xp->evaluate('string(//module[./idJS[. = "001"]]/addressPLC[1])');

Done. Also it does work as well with getElementsByTagName. See the online Demo:

<?php

$buffer = <<<BUFFER
<config>
  <module>
    <idJS >001</idJS>
    <addressPLC>41000</addressPLC>
  </module>
  <module>
    <idJS >002</idJS>
    <addressPLC>42000</addressPLC>
  </module> 
</config>
BUFFER;

$doc = new DOMDocument();
$doc->loadXML( $buffer );

$modules = $doc->getElementsByTagName( "module" );

var_dump($modules);

foreach ($modules as $module)
{
    $ids = $module->getElementsByTagName('idJS');
    var_dump($ids);

    foreach ($ids as $id) {
        var_dump($id->nodeValue);
        if ($id->nodeValue == '001') {
            # ...
        }
    }
}

$xp = new DOMXpath($doc);
echo $xp->evaluate('string(//module[./idJS[. = "001"]]/addressPLC[1])');
hakre
  • 193,403
  • 52
  • 435
  • 836