php - How to get the value of a very specific XML element...?

Solution:

One way is that you could loop over all $xml->source and exit from the loop when the value is important like so using a foreach loop:

<?php
    $xml=simplexml_load_file("data.xml") or die("Error: Cannot create object");
    foreach($xml->source as $source){
        if($source['mount'] == '/stu'){
            echo $source->important;
            break;
        }
    }
?>

Answer

Solution:

With XPath, you describe what you want to select. Starting form the top of the document at the "root node" with / and then "walk" down the levels of the tree with each "step".

If you are looking for all of the important elements that are children of source elements, which are children of stats:

/stats/source/important

Or you could look for important elements anywhere, at any level within the document with:

//important

And if you only want the important element that is a child of source with the attribute mount="/stu":

/stats/source[@mount="/stu"]/important

Applied:

$result = $xml->xpath('/stats/source[@mount="/stu"]/important'); 
foreach ($result as $important){
    echo '/stats/source[@mount="/stu"]/important: ', $important, "\n";
}

Answer

Solution:

Using DOMDocument & DOMXPath make the task of retrieving particular nodes from within a simple XML file like this quite straightforward.

The XML posted contained errors with the data tags as mentioned - these were caught by libxml as it has it's own error handling routines.

$xml='<stats>
        <data1>lorem</data1>
        <data2>ipsum</data2>
        <source mount="/mno">
            <thing>1.0</thing>
            <somethingelse>10</somethingelse>
            <important>12345</important>
            <more>word</more>
        </source>
        <source mount="/pqr">
            <thing>1.0</thing>
            <somethingelse>10</somethingelse>
            <important>23456</important>
            <more>word</more>
        </source>
        <source mount="/stu">
            <thing>1.0</thing>
            <somethingelse>10</somethingelse>
            <important>34567</important>
            <more>word</more>
        </source>
        <source mount="/vwx">
            <thing>1.0</thing>
            <somethingelse>10</somethingelse>
            <important>45678</important>
            <more>word</more>
        </source>
    </stats>';


libxml_use_internal_errors( true ) ;
$dom=new DOMDocument();
$dom->validateOnParse=false;
$dom->recover=true;
$dom->strictErrorChecking=false;
$dom->loadXML( $xml );
$errors=libxml_get_errors();

$xp=new DOMXPath( $dom );
if( $xp ){
    $expr='//source[@mount="/stu"]/important';
    $col=$xp->query( $expr );
    
    if( $col && $col->length > 0 )echo $col->item(0)->nodeValue;
}

The XPath expression $expr='//source[@mount="/stu"]/important'; says to find any source node that has an attribute mount that exactly equals the desired string /stu - considerably more complex matching of nodes and attributes can be done than this.

This outputs:

34567

Source