开发者

Retrieving a subset of XML nodes with PHP

Using PHP, how do I get an entire subset of nodes from an XML document? I can retrieve something like:

<?xml version="1.0" encoding="utf-8"?>
<people>
  <certain>
    <name>Jane Doe</name>
    <age>21</age>
  </certain>
  <certain>
  <certain>
    <name>John Smith</name>
    <age>34</age>
  </certain>
</people>

But what if I only want to return the child nodes of like this?

  <certain>
    <name>Jane Doe</name>
    <age>21</age>
  </certain>
  <certain>
  <certain>
    <name>John Smith</name>
    <age>34</age>
  </certain>

EDIT: I'm trying to get a subset of XML and pass that directly, not an object like simplexml would give me. I am basically trying to get PHP to do what .NET's OuterXml does... return literally the above subset of XML as is... no interpreting or converting or creating a new XML file or anything... just extract those nodes in situ and pass them on. Am I going to have to get the XML file, parse out what I need and then rebuild it as a new XML file? If so th开发者_StackOverflowen I need to get rid of the <?xml version="1.0" encoding="utf-8"?> bit... ugh.


The answer would be to use XPath.

$people = simplexml_load_string(
    '<?xml version="1.0" encoding="utf-8"?>
    <people>
      <certain>
        <name>Jane Doe</name>
        <age>21</age>
      </certain>
      <certain>
        <name>John Smith</name>
        <age>34</age>
      </certain>
    </people>'
);

// get all <certain/> nodes
$people->xpath('//certain');

// get all <certain/> nodes whose <name/> is "John Smith"
print_r($people->xpath('//certain[name = "John Smith"]'));

// get all <certain/> nodes whose <age/> child's value is greater than 21
print_r($people->xpath('//certain[age > 21]'));

Take 2

So apparently you want to copy some nodes from a document into another document? SimpleXML doesn't support that. DOM has methods for that but they're kind of annoying to use. Which one are you using? Here's what I use: SimpleDOM. In fact, it's really SimpleXML augmented with DOM's methods.

include 'SimpleDOM.php';
$results = simpledom_load_string('<results/>');

foreach ($people->xpath('//certain') as $certain)
{
    $results->appendChild($certain);
}

That routine finds all <certain/> node via XPath, then appends them to the new document.


You could use DOMDocument.GetElementsByTagName or you could:

Use XPath?

<?php
$xml = simplexml_load_file("test.xml");

$result = $xml->xpath("//certain");

print_r($result);
?>


Use DOM and XPath. Xpath allows you to select nodes (and values) from an XML DOM.

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);

$result = '';
foreach ($xpath->evaluate('/people/certain') as $node) {
  $result .= $dom->saveXml($node);
}

echo $result;

Demo: https://eval.in/162149

DOMDocument::saveXml() has a context argument. If provided it saves that node as XML. Much like outerXml(). PHP is able to register your own classes for the DOM nodes, too. So it is even possible to add an outerXML() function to element nodes.

class MyDomElement extends DOMElement {
  public function outerXml() {
    return $this->ownerDocument->saveXml($this);
  }
}

class MyDomDocument extends DOMDocument {
  public function __construct($version = '1.0', $encoding = 'utf-8') {
    parent::__construct($version, $encoding);
    $this->registerNodeClass('DOMElement', 'MyDomElement');
  }
}

$dom = new MyDomDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);

$result = '';
foreach ($xpath->evaluate('/people/certain') as $node) {
  $result .= $node->outerXml();
}

echo $result;

Demo: https://eval.in/162157


See http://www.php.net/manual/en/domdocument.getelementsbytagname.php


The answer turned out to be a combination of the xpath suggestion and outputting with asXML().

Using the example given by Josh Davis:

$people = simplexml_load_string(
      <?xml version="1.0" encoding="utf-8"?>
        <people>
          <certain>
            <name>Jane Doe</name>
            <age>21</age>
          </certain>
          <certain>
            <name>John Smith</name>
            <age>34</age>
          </certain>
        </people>'
    );

    // get all <certain/> nodes
    $nodes = $people->xpath('/people/certain');

    foreach ( $nodes as $node ) {
      $result .= $node->asXML()."\n";
    }
    echo $result;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜