【问题标题】:How to use xquery to find node and addChild to it?如何使用 xquery 查找节点并将其添加到它?
【发布时间】:2015-02-13 16:31:34
【问题描述】:

是否可以使用 xpath/xquery 来查询特定的 xml 节点,然后向其中导入/添加子节点?

示例(取自 http://codepad.org/gJ1Y2LjM 的代码,在类似问题中提出,但不相同):

1。 我想添加一个数组

$book = array('isbn'=>123456789099, 'title' => 'Harry Potter 3', 'author' => 'J K. Rowling', 'edition' => '2007');

2。 到现有的 XML。

$doc = new DOMDocument();
$doc->loadXML('<?xml version="1.0"?>
<books>
    <book>
        <isbn>123456789098</isbn>
        <title>Harry Potter</title>
        <author>J K. Rowling</author>
        <edition>2005</edition>
    </book>
    <book>
        <placeItHere></placeItHere>
        <isbn>1</isbn>
        <title>stuffs</title>
        <author>DA</author>
        <edition>2014</edition>
    </book>
</books>');

3。 为此,它使用了以下片段。

$fragment = $doc->createDocumentFragment();
$fragment->appendXML("    <book>
<isbn>{$book['isbn']}</isbn>
        <title>{$book['title']}</title>
        <author>{$book['author']}</author>
        <edition>{$book['edition']}</edition>
    </book>
");

4。 但是我没有将它附加到根节点,而是几乎所有我在互联网上找到的示例:

$doc->documentElement->appendChild($fragment);

5。 我想将它(p.ex)附加到 /books/book/placeItHere 中的节点,而不是使用 getElementbyId 或 tagName,而是使用 xpath/xquery。我试过了

$xp = new domxpath($doc);
$parent = $xp->query("books/book/placeItHere");

到达节点,但从未设法将其用作父节点。

问题:如何使用该位置附加Child $fragment?有可能吗?

**YOUR BEAUTIFUL MAGIC**

最后我会保存它。

echo $doc->saveXML();

感谢您对我的任何帮助。

【问题讨论】:

  • 好问题。你能告诉我们你尝试了什么代码,结果是什么?它是否给出了错误消息?
  • 我尝试了很多不同的方法,但我认为我缺少一些基本的东西,比如如何将 xquery 的结果转换为可以用作 DOMDocument 的东西。通常错误是:“代码”致命错误:在非对象“代码”上调用成员函数 appendChild() -> 当我尝试以与 $dom 相关的任何方式直接使用 $parent 时。示例:$parent->item(0)->appendChild($fragment); #ERROR...我正在尝试获取以前的示例,但我认为我现在无法全部获取它们,因为我不在我的机器上)

标签: php xml xpath xquery


【解决方案1】:

几个问题:

  1. 您的 xpath 表达式应为 /books/book/placeItHere(以 / 开头)。
  2. DOMXPath::query() 返回 DOMNodeList 而不是 DOMNode,因此您需要从中获取 item()

我很少推荐使用文档片段,因为使用原始 XML 快速而松散地经常会导致问题。例如,如果您的书名包含一个 & 符号 appendXML(),则会出现解析器错误。

我建议使用createElement()createTextNode(),它们会自动处理将&amp;amp; 转换为&amp;amp; 之类的内容。


示例:

$xml = <<<'XML'
<?xml version="1.0"?>
<books>
    <book>
        <isbn>123456789098</isbn>
        <title>Harry Potter</title>
        <author>J K. Rowling</author>
        <edition>2005</edition>
    </book>
    <book>
        <placeItHere></placeItHere>
        <isbn>1</isbn>
        <title>stuffs</title>
        <author>DA</author>
        <edition>2014</edition>
    </book>
</books>
XML;

$book = [
    'isbn'    => 123456789099,
    'title'   => 'Harry Potter 3',
    'author'  => 'J K. Rowling',
    'edition' => '2007'
];

$dom = new DOMDocument();
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);

$placeItHere = $xpath->query('/books/book/placeItHere')->item(0);
$newBook = $placeItHere->appendChild($dom->createElement('book'));
foreach ($book as $part => $value) {
    $element = $newBook->appendChild($dom->createElement($part));
    $element->appendChild($dom->createTextNode($value));
}

echo $dom->saveXML();

输出:

<?xml version="1.0"?>
<books>
  <book>
    <isbn>123456789098</isbn>
    <title>Harry Potter</title>
    <author>J K. Rowling</author>
    <edition>2005</edition>
  </book>
  <book>
    <placeItHere>
      <book>
        <isbn>123456789099</isbn>
        <title>Harry Potter 3</title>
        <author>J K. Rowling</author>
        <edition>2007</edition>
      </book>
    </placeItHere>
    <isbn>1</isbn>
    <title>stuffs</title>
    <author>DA</author>
    <edition>2014</edition>
  </book>
</books>

【讨论】:

  • 感谢您的回复...我试过了:$xp = new DOMXPath($doc); $placeItHere = $xp->query('/books/book/placeItHere')->item(0); $newBook = $placeItHere->appendChild($fragment);它奏效了(真棒!)。我想我以前试过这个,但没有第一个'/',所以再次感谢你。我只使用片段,因为我正在导入的实际代码比示例更大更深。你能告诉我使用片段选项而不是创建每个元素可能会出现什么样的问题吗?
  • @Paull Crovella:正如我尝试过的对我的问题的评论:$placeItHere = $xpath->query("books/book/placeItHere"); $placeItHere->item(0)->appendChild($fragment); -> 不工作.....我试过你的答案: $placeItHere = $xpath->query('/books/book/placeItHere')->item(0); $placeItHere->appendChild($fragment); -> 工作......我想这是你指出的前导'/'的问题(我现在很惭愧:)......)。让我检查一下新的答案,感谢您对文档片段的回答。
  • 我尝试了 & 符号,并预计它会引发 7 个警告。我一定会考虑你的建议。将您的答案标记为正确。
猜你喜欢
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多