1

I have a XML object result from my database containing settings.

I am trying to access the values for a particular settingName:

    SimpleXMLElement Object
(
[settings] => Array
    (
        [0] => SimpleXMLElement Object
            (
                [settingName] => Test
                [settingDescription] => Testing
                [requireValue] => 1
                [localeID] => 14
                [status] => 1
                [value] => 66
                [settingID] => 5
            )

        [1] => SimpleXMLElement Object
            (
                [settingName] => Home Page Stats
                [settingDescription] => Show the Top 5 Teammate / Teamleader stats?
                [requireValue] => 0
                [localeID] => 14
                [status] => 0
                [value] => SimpleXMLElement Object
                    (
                    )

                [settingID] => 3
            )

    )

)

I tried using xPath and have this so far:

$value = $fetchSettings->xpath("//settingName[text()='Test']/../value");

which returns:

Array ( [0] => SimpleXMLElement Object ( [0] => 66 ) )

How can I get the actual value and not just another array/object?

The end result will just be 66 for the example above.

IMSoP
  • 89,526
  • 13
  • 117
  • 169
SBB
  • 8,560
  • 30
  • 108
  • 223
  • With a decent PHP version: `$value = (string) reset($fetchSettings->xpath("//settingName[text()='Test']/../value"));` - will give a zero-length string in case there was no result, otherwise will always return the first result node (in document order). – hakre Jul 30 '14 at 11:39

3 Answers3

2

Because every element in a XML-file can appear as multiple times the parser always returns an array. If you are sure, that it is only a single item you can use current()

echo (string) current($value);

Note, that I cast the SimpleXMLElement to a string (see http://php.net/manual/simplexmlelement.tostring.php ) to get the actual value.

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
2
  1. SimpleXMLElement::xpath() returns a plain PHP array of "search results"; the first result will always be index 0 if any results were found.
  2. Each "search result" is a SimpleXMLElement object, which has a magic __toString() method for getting the direct text content of a node (including CDATA, but including text inside child nodes, etc). The simplest way to call it is with (string)$my_element; (int)$my_element will also invoke it, then convert the result to an integer.

So:

 $xpath_results = $fetchSettings->xpath("//settingName[text()='Test']/../value");
 if ( count($xpath_results) > 0 ) {
      $value = (string)$xpath_results[0];
 }

Alternatively, the DOMXPath class can return results other than element and attribute nodes, due to the DOM's richer object model. For instance, you can have an XPath expression ending //text() to refer to the text content of a node, rather than the node itself (SimpleXML will do the search, but give you an element object anyway).

The downside is it's rather more verbose to use, but luckily you can mix and match the two sets of functions (using dom_import_simplexml() and its counterpart) as they have the same underlying representation:

 // WARNING: Untested code. Please comment or edit if you find a bug!
 $fetchSettings_dom = dom_import_simplexml($fetchSettings);
 $xpath = new DOMXPath($fetchSettings_dom->ownerDocument);
 $value = $xpath->evaluate(
      "//settingName[text()='Test']/../value/text()",
      $fetchSettings_dom
 );
IMSoP
  • 89,526
  • 13
  • 117
  • 169
0

Use DomXPath class instead. http://php.net/manual/en/domxpath.evaluate.php The sample from php.net is just equivalent what you'd like to achieve:

<?php
$doc = new DOMDocument;
$doc->load('book.xml');
$xpath = new DOMXPath($doc);
$tbody = $doc->getElementsByTagName('tbody')->item(0);
// our query is relative to the tbody node
$query = 'count(row/entry[. = "en"])';
$entries = $xpath->evaluate($query, $tbody);
echo "There are $entries english books\n";

In this way, you can get values straight from the XML.

Aron Novak
  • 314
  • 1
  • 14