gpt4 book ai didi

使用默认 namespace 绑定(bind)对 XML 进行 PHP xpath 查询

转载 作者:可可西里 更新时间:2023-11-01 13:40:35 24 4
gpt4 key购买 nike

我对主题问题有一个解决方案,但它是一个 hack,我想知道是否有更好的方法来做到这一点。

下面是一个示例 XML 文件和一个 PHP CLI 脚本,该脚本执行作为参数给出的 xpath 查询。对于这个测试用例,命令行是:

./xpeg "//MainType[@ID=123]"

最奇怪的是这一行,没有它我的方法就不起作用:

$result->loadXML($result->saveXML($result));

据我所知,这只是重新解析修改后的 XML,在我看来这不是必需的。

有没有更好的方法在 PHP 中对这个 XML 执行 xpath 查询?


XML(注意默认命名空间的绑定(bind)):

<?xml version="1.0" encoding="utf-8"?>
<MyRoot
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.com/data http://www.example.com/data/MyRoot.xsd"
xmlns="http://www.example.com/data">
<MainType ID="192" comment="Bob's site">
<Price>$0.20</Price>
<TheUrl><![CDATA[http://www.example.com/path1/]]></TheUrl>
<Validated>N</Validated>
</MainType>
<MainType ID="123" comment="Test site">
<Price>$99.95</Price>
<TheUrl><![CDATA[http://www.example.com/path2]]></TheUrl>
<Validated>N</Validated>
</MainType>
<MainType ID="922" comment="Health Insurance">
<Price>$600.00</Price>
<TheUrl><![CDATA[http://www.example.com/eg/xyz.php]]></TheUrl>
<Validated>N</Validated>
</MainType>
<MainType ID="389" comment="Used Cars">
<Price>$5000.00</Price>
<TheUrl><![CDATA[http://www.example.com/tata.php]]></TheUrl>
<Validated>N</Validated>
</MainType>
</MyRoot>

PHP CLI 脚本:

#!/usr/bin/php-cli
<?php

$xml = file_get_contents("xpeg.xml");

$domdoc = new DOMDocument();
$domdoc->loadXML($xml);

// remove the default namespace binding
$e = $domdoc->documentElement;
$e->removeAttributeNS($e->getAttributeNode("xmlns")->nodeValue,"");

// hack hack, cough cough, hack hack
$domdoc->loadXML($domdoc->saveXML($domdoc));

$xpath = new DOMXpath($domdoc);

$str = trim($argv[1]);
$result = $xpath->query($str);
if ($result !== FALSE) {
dump_dom_levels($result);
}
else {
echo "error\n";
}

// The following function isn't really part of the
// question. It simply provides a concise summary of
// the result.
function dump_dom_levels($node, $level = 0) {
$class = get_class($node);
if ($class == "DOMNodeList") {
echo "Level $level ($class): $node->length items\n";
foreach ($node as $child_node) {
dump_dom_levels($child_node, $level+1);
}
}
else {
$nChildren = 0;
foreach ($node->childNodes as $child_node) {
if ($child_node->hasChildNodes()) {
$nChildren++;
}
}
if ($nChildren) {
echo "Level $level ($class): $nChildren children\n";
}
foreach ($node->childNodes as $child_node) {
if ($child_node->hasChildNodes()) {
dump_dom_levels($child_node, $level+1);
}
}
}
}
?>

最佳答案

解决方案是使用命名空间,而不是摆脱它。

$result = new DOMDocument();
$result->loadXML($xml);

$xpath = new DOMXpath($result);
$xpath->registerNamespace("x", trim($argv[2]));

$str = trim($argv[1]);
$result = $xpath->query($str);

并在命令行中调用它(注意 XPath 表达式中的 x:)

./xpeg "//x:MainType[@ID=123]" "http://www.example.com/data"

你可以通过以下方式让它更 Shiny

  • 自己找出默认命名空间(通过查看文档元素的命名空间属性)
  • 在命令行支持多个命名空间并在$xpath->query()之前注册它们
  • 支持xyz=http//namespace.uri/形式的参数来创建自定义命名空间前缀

底线是:在 XPath 中,当您真正指的是 //namespace:foo 时,您不能查询 //foo。这些根本不同,因此选择不同的节点。 XML 可以定义默认 namespace (因此可以在文档中删除显式 namespace 使用)这一事实并不意味着您可以在 XPath 中删除 namespace 使用。

关于使用默认 namespace 绑定(bind)对 XML 进行 PHP xpath 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6475394/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com