使用PHP SimpleXML Xpath解析带有名称空间的XML时出现问题
有几篇文章是关于PHP和SimpleXML以及名称空间的,但是没有一篇能够解决我面临的挑战。这里是一个小的XML体,代表我遇到麻烦的一个较大的XML体,尽管如此,挑战是相同的。我无法获取任何xpath查询来返回所需的数据。注意以下几点使用PHP SimpleXML Xpath解析带有名称空间的XML时出现问题,php,xpath,namespaces,simplexml,Php,Xpath,Namespaces,Simplexml,有几篇文章是关于PHP和SimpleXML以及名称空间的,但是没有一篇能够解决我面临的挑战。这里是一个小的XML体,代表我遇到麻烦的一个较大的XML体,尽管如此,挑战是相同的。我无法获取任何xpath查询来返回所需的数据。注意以下几点 $xml = <<<EOD <blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah"> <blah:wrap>
$xml = <<<EOD
<blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah">
<blah:wrap>
<chap:wrap>
<title>My Book</title>
<chapter id="1">
<title>Chapter 1</title>
<para>Donec velit. Nullam eget tellus vitae</para>
</chapter>
<chapter id="2">
<title>Chapter 2</title>
<para>Lorem ipsum dolor sit amet</para>
</chapter>
</chap:wrap>
</blah:wrap>
</blah:book>
EOD;
当“chap”更普遍时,会出现以下问题:
$xml = <<<EOD
<blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah">
<blah:wrap>
<chap:wrap>
<chap:title>My Book</chap:title>
<chap:chapter id="1">
<chap:title>Chapter 1</chap:title>
<chap:para>Donec velit. Nullam eget tellus vitae</chap:para>
</chap:chapter>
<chap:chapter id="2">
<chap:title>Chapter 2</chap:title>
<chap:para>Lorem ipsum dolor sit amet</chap:para>
</chap:chapter>
</chap:wrap>
</blah:wrap>
</blah:book>
EOD;
我已尝试注册命名空间:
$sxe = new SimpleXMLElement($xml);
$sxe->registerXPathNamespace('chap', 'http://example.org/chapter-title');
$result = $sxe->xpath('/node()/*/*');
var_dump($result);
但结果还是一样的:
array(1) {
[0]=>
object(SimpleXMLElement)#2 (0) {
}
}
我尝试了许多不同的xpath查询,其中没有一个会返回数组结构中的整个xml体,如上所示,从第一个xml体开始。这里有几个,但我尝试过更疯狂的事情出于绝望,没有一个奏效
$result = $sxe->xpath('/node()/chap:*/*');
$result = $sxe->xpath('/node()/*/chap:*');
一些帖子建议删除所有的名称空间,然后不用担心它,但是,应该有一种方法来解析它并检索整个主体,就像在第一个示例中可能的那样。不幸的是,我空手而来。我还要承认,我不明白为什么第一个正文中出现的一个“chap”名称空间不会对初始xpath查询造成问题。我希望有人能给我指出正确的方向。也许一个可能的解决方案是将其用作xpath表达式: $result=$sxe->xpath('//blah:book/blah:wrap') 返回可以从中获取第一项的数组。这将是您可以使用该方法并传递名称空间的类型形式 您可以在foreach中循环子项,
$res
变量的类型为simplexmlement。然后,您可以检查属性是否已设置并获取数据
例如:
$xml = <<<EOD
<blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah">
<blah:wrap>
<chap:wrap>
<chap:title>My Book</chap:title>
<chap:chapter id="1">
<chap:title>Chapter 1</chap:title>
<chap:para>Donec velit. Nullam eget tellus vitae</chap:para>
</chap:chapter>
<chap:chapter id="2">
<chap:title>Chapter 2</chap:title>
<chap:para>Lorem ipsum dolor sit amet</chap:para>
</chap:chapter>
</chap:wrap>
</blah:wrap>
</blah:book>
EOD;
$sxe = new SimpleXMLElement($xml);
$result = $sxe->xpath('//blah:book/blah:wrap');
foreach ($result[0]->children('http://example.org/chapter-title') as $res) {
if (isset($res->title)) {
$bookTitle = $res->title->__toString();
}
if (isset($res->chapter)) {
foreach ($res->chapter as $chapter) {
$chapterTitle = $chapter->title->__toString();
$chapterPara = $chapter->para->__toString();
}
}
}
$xml=title)){
$bookTitle=$res->title->\uuuuToString();
}
如果(isset($res->章节)){
foreach($res->章为$chapter){
$chapterTitle=$chapter->title->\uuuu toString();
$chapterPara=$chapter->para->;
}
}
}
这对我来说不太合适。我需要的是能够在多维数组中恢复所有内容,就像没有名称空间一样。虽然这可能会使我在前额疼痛后得到类似的结果,但这需要我事先知道元素名称,而这并不是我想要达到的目的。
$result = $sxe->xpath('/node()/chap:*/*');
$result = $sxe->xpath('/node()/*/chap:*');
$xml = <<<EOD
<blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah">
<blah:wrap>
<chap:wrap>
<chap:title>My Book</chap:title>
<chap:chapter id="1">
<chap:title>Chapter 1</chap:title>
<chap:para>Donec velit. Nullam eget tellus vitae</chap:para>
</chap:chapter>
<chap:chapter id="2">
<chap:title>Chapter 2</chap:title>
<chap:para>Lorem ipsum dolor sit amet</chap:para>
</chap:chapter>
</chap:wrap>
</blah:wrap>
</blah:book>
EOD;
$sxe = new SimpleXMLElement($xml);
$result = $sxe->xpath('//blah:book/blah:wrap');
foreach ($result[0]->children('http://example.org/chapter-title') as $res) {
if (isset($res->title)) {
$bookTitle = $res->title->__toString();
}
if (isset($res->chapter)) {
foreach ($res->chapter as $chapter) {
$chapterTitle = $chapter->title->__toString();
$chapterPara = $chapter->para->__toString();
}
}
}