使用 DOMXml 和 Xpath 更新 XML 条目

2024-03-21

您好,我知道这里有很多关于这三个主题组合在一起更新 XML 条目的问题,但似乎每个人都针对给定的问题。

我花了一些时间试图理解 XPath 及其方式,但我仍然无法得到我需要做的事情。

开始了

我有这个 XML 文件

 <?xml version="1.0" encoding="UTF-8"?>
<storagehouse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:noNamespaceSchemaLocation="schema.xsd">
    <item id="c7278e33ef0f4aff88da10dfeeaaae7a">
        <name>HDMI Cable 3m</name>
        <weight>0.5</weight>
        <category>Cables</category>
        <location>B3</location>
    </item>
    <item id="df799fb47bc1e13f3e1c8b04ebd16a96">
        <name>Dell U2410</name>
        <weight>2.5</weight>
        <category>Monitors</category>
        <location>C2</location>
    </item>
    </storagehouse>

我想做的是在需要时更新/编辑上面的任何节点。我将为此制作一个 Html 表单。 但我最大的问题是如何找到并更新所需的节点并更新它?

这里我有一些我想做的事情

<?php

 function fnDOMEditElementCond()
   {
       $dom = new DOMDocument();
       $dom->load('storage.xml');
       $library = $dom->documentElement;
       $xpath = new DOMXPath($dom);
      // I kind of understand this one here
       $result = $xpath->query('/storagehouse/item[1]/name');
       //This one not so much
       $result->item(0)->nodeValue .= ' Series';
       // This will remove the CDATA property of the element.
       //To retain it, delete this element (see delete eg) & recreate it with CDATA (see create xml eg).

       //2nd Way
       //$result = $xpath->query('/library/book[author="J.R.R.Tolkein"]');
      // $result->item(0)->getElementsByTagName('title')->item(0)->nodeValue .= ' Series';
       header("Content-type: text/xml");
       echo $dom->saveXML();


   }
?>

有人可以给我一个带有属性等的示例,这样当用户决定更新所需的节点时,我可以使用 XPath 找到该节点然后更新它吗?


下面的例子是利用simplexml这是一个亲密的朋友DOMDocument。无论你使用哪种方法,显示的 xpath 都是相同的,我使用simplexml这里是为了保持低代码。我将展示更高级的DOMDocument稍后举例。

那么关于xpath:如何找到节点并更新它。首先如何找到节点:

该节点具有元素/标记名item。你正在里面寻找它storagehouseelement,它是 XML 文档的根元素。全部item文档中的元素在 xpath 中表达如下:

/storagehouse/item

首先从根源入手storagehouse, then item。除以/。你已经知道了,所以有趣的部分是如何只采取那些item具有特定 ID 的元素。为此,使用谓词并在末尾添加:

/storagehouse/item[@id="id"]

这将返回所有item再次元素,但这次只有那些具有该属性的元素id与价值id(细绳)。例如,在您的情况下,使用以下 XML:

$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<storagehouse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="schema.xsd">
    <item id="c7278e33ef0f4aff88da10dfeeaaae7a">
        <name>HDMI Cable 3m</name>
        <weight>0.5</weight>
        <category>Cables</category>
        <location>B3</location>
    </item>
    <item id="df799fb47bc1e13f3e1c8b04ebd16a96">
        <name>Dell U2410</name>
        <weight>2.5</weight>
        <category>Monitors</category>
        <location>C2</location>
    </item>
</storagehouse>
XML;

那个xpath:

/storagehouse/item[@id="df799fb47bc1e13f3e1c8b04ebd16a96"]

将返回计算机监视器(因为存在具有该 id 的此类项目)。如果有多个项目具有相同的 id 值,则将返回多个。如果没有,则不会返回。因此,让我们将其包装到代码示例中:

$simplexml = simplexml_load_string($xml);
$result = $simplexml->xpath(sprintf('/storagehouse/item[@id="%s"]', $id));
if (!$result || count($result) !== 1) {
    throw new Exception(sprintf('Item with id "%s" does not exists or is not unique.', $id));
}
list($item) = $result;

在这个例子中,$titem is the SimpleXMLElement http://php.net/SimpleXMLElement该计算机监视器的对象 xml 元素名称项目。

现在进行更改,这非常容易SimpleXML在你的情况下:

$item->category = 'LCD Monitor';

最后看看结果:

echo $simplexml->asXML();

是的,这就是全部SimpleXML在你的情况下。

如果你想这样做DOMDocument,它的工作原理非常相似。但是,为了更新元素的值,您还需要访问该项目的子元素。让我们看看下面的示例,它首先也获取该项目。如果你与SimpleXML上面的例子,你可以看到事情并没有真正的不同:

$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$result = $xpath->query(sprintf('/storagehouse/item[@id="%s"]', $id));
if (!$result || $result->length !== 1) {
    throw new Exception(sprintf('Item with id "%s" does not exists or is not unique.', $id));
}
$item = $result->item(0);

Again, $item包含计算机监视器的项目 XML 元素。但这一次作为DOMElement http://php.net/DOMElement。要修改category那里的元素(或者更准确地说,它是nodeValue),需要首先获得孩子。您可以使用 xpath 再次执行此操作,但这次使用相对于$item元素:

./category

假设总有一个category中的子元素item元素,可以写成这样:

$category = $xpath->query('./category', $item)->item(0);

$category现在包含第一个category的子元素$item。剩下的就是更新它的值:

$category->nodeValue = "LCD Monitor";

最后看看结果:

echo $doc->saveXML();

就是这样。无论您选择 SimpleXML 还是 DOMDocument,这取决于您的需求。您甚至可以在两者之间切换。您可能想要映射并检查更改:

$repository = new Repository($xml);
$item = $repository->getItemByID($id);
$item->category = 'LCD Monitor';
$repository->saveChanges();
echo $repository->getXML();

自然这需要莫尔斯电码 https://gist.github.com/0f0a65234fa139b95ee1,对于这个答案来说太多了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 DOMXml 和 Xpath 更新 XML 条目 的相关文章

  • 从 stdin 读取后,PHP 在每行上给出尾随“=”

    stdin 的内容因自动换行和尾随 而被损坏 这显然破坏了我需要发布的 URL 我需要从电子邮件中提取 URL 链接 然后发布该 URL 因此 我使用我在互联网上看到的标准代码片段将电子邮件传输到 cpanel 中的 php 脚本 fd f
  • PHP:__toString() 和 json_encode() 不能很好地协同工作

    我遇到了一个奇怪的问题 我不知道如何解决它 我有几个类 它们都是 JSON 对象的 PHP 实现 这是问题的说明 class A protected a public function construct this gt a array n
  • PDO 如何在执行 rollBack() 函数之前回滚查询?

    这是我的脚本 try dbh con gt beginTransaction stmt1 dbh conn gt prepare UPDATE activate account num SET num num 1 stmt1 gt exec
  • Android 中的 XmlPullParser 陷入困境

    经过多个小时的搜索和调试后 我仍然停留在同一个地方 并且 Eclipse 没有帮助我 我试图解析这个 RSS 提要 http fr espnf1 com rss motorsport story feeds 0 xml type 2 这很简
  • php简单xml如何读取具有不同子节点级别的多个节点

    我有一个 xml 文件 其中包含不同的命名节点和多级子节点 每个节点之间都不同 我应该如何访问数据 需要很多嵌套的for循环吗 以下是 xml 代码示例
  • 如何在 laravel/php 中访问该集合的内容

    我是 Laravel 的新手 正在做一个构建迷你社交网络应用程序的项目 我有一个与用户模型有关系的帖子模型 我有一个帖子页面 其中仅显示经过身份验证的用户及其朋友的帖子 在我的 PostController 中 我像这样查询经过身份验证的用
  • XDocument.Save() 删除我的 实体

    我编写了一个工具来使用 C 和 Linq to XML 修复一些 XML 文件 即插入一些缺失的属性 值 该工具将现有 XML 文件加载到 XDocument 对象中 然后 它向下解析节点以插入丢失的数据 之后 它调用 XDocument
  • 通过日期选择器过滤查询后检索具有特定值的行数[重复]

    这个问题在这里已经有答案了 目前 我正在使用 CodeIgniter 来检索特定时间范围内的数据 所有这些条目都有一个状态 我想将具有相同状态的所有条目分组并将其显示在各自的标题中 目前 这是我的模型类 其中我有以下条目来返回特定日期范围内
  • 在php中的字符串数组中查找字符串的开头[重复]

    这个问题在这里已经有答案了 我知道我们有 php in array 函数 但我正在寻找一种方法来查找以特定字符串开头的字符串数组中的值 例如找到 search string div 1 div 在这样的数组中 array sample gt
  • PHP: $arr['key'] 上的 is_array 不存在 'key'

    我的一所大学似乎在我编写的代码中存在 未定义索引 错误 我的这段代码如下所示 if is array arr key 我的目的是检查 arr 是否有一个名为 key 的键 以及该键的值是否是数组本身 我应该这样做吗 if isset arr
  • 流畅的 NHibernate 和 XML 列

    我正在从头开始构建一个新站点 并正在考虑使用 Fluent NHibernate 作为我的 ORM 我认为它可以轻松处理所有事情 可能除了我的 XML 列 我从来没有使用 NHibernate 构建过网站 尽管我使用过 Hibernate
  • 密码验证 PHP 正则表达式

    我是正则表达式的新手 我需要使用 php 验证密码 并使用正则表达式执行以下密码策略 密码 必须至少有 8 个字符 必须有2个号码 允许的符号有 我已经尝试过以下方法 d A Za z 0 9A Za z 以下完全符合您的要求 d d 0
  • PHP 静态变量用双引号引起来

    如何让 PHP 计算双引号中的静态变量 我想做这样的事情 log self CLASS METHOD entering 我尝试过各种 组合来获取变量值self CLASS 但没有任何效果 我目前已经解决了字符串连接问题 但输入起来很痛苦 l
  • Laravel 雄辩的 withCount() 应该比 with() 慢

    所以我问这个的原因是在我当前的应用程序中withCount 与仅通过以下方式获取关系的所有数据相比 响应时间几乎增加了三倍with 并只是从前端获取长度 javascript 我认为使用的要点withCount 是为了加快查询速度 但也许我
  • 如何在 PHP 中递归删除目录及其全部内容(文件+子目录)? [复制]

    这个问题在这里已经有答案了 如何在 PHP 中删除目录及其全部内容 文件和子目录 手册页中的用户贡献部分rmdir http www php net rmdir包含一个不错的实现 function rrmdir dir if is dir
  • Symfony 4.1 组件 - 依赖注入问题

    我正在用 PHP 重构旧应用程序 我正在尝试使用 Symfony 依赖注入组件将服务注入控制器 或其他服务 但我不知道如何实现这一点 因为 symphony 文档比框架组件更适合使用框架 我已经有了自己的内核 包含所有服务和控制器的容器 控
  • 使用 PHP 将子项添加到 XML 文件

    添加子项时 抛出此错误 无法添加孩子 父级不是 XML 树的永久成员 我无法解决这个问题 这是我的代码 if visited FIRST xml new SimpleXMLElement
  • 使用 foreach 循环和 XmlNodeList C# 将新节点附加到节点列表

    目前我处理的是这样的XML类型 XML FILE http 20drive google com open id 0By5BxgNi9eGcRldxcEZNU0FDTzQ 参考XML文件 我想检查一个节点 如果找不到该节点 我必须将该节点附
  • PHP strtotime返回Mysql UNIX_TIMESTAMP的不同值

    我在 stackoverflow 上搜索过帖子 发现了一些类似的帖子 但我认为这是一篇不同的帖子 我的 PHP 和 Mysql 服务器的时区全部设置为 UTC 在表中我使用时间戳字段 值为 2010 11 08 02 54 15 我使用这样
  • 使用 php 变量更改 css 类

    这里需要您的帮助 正如标题所示 我正在尝试使用 PHP 变量更改 css 类 所以基本上我想创建一个回显某些代码的循环 但我希望第一个循环中的 div 类有所不同 它应该被隐藏 这是我为使问题变得清晰而编写的简化代码 我不知道错误在哪里 请

随机推荐