gpt4 book ai didi

php - SimpleXMLElement-> xpath()显示不在对象中的数据

转载 作者:行者123 更新时间:2023-12-03 17:04:25 26 4
gpt4 key购买 nike

我正在查询YouTrack的网络服务以获取问题列表。响应是如下所示的XML:

<issueCompacts>
<issue id="XX-1">
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>Bug</value>
</field>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Bill-to">
<value>NBS</value>
</field>
</issue>
<issue id="XX-2">
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>New Feature</value>
</field>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Bill-to">
<value>NBS</value>
</field>
</issue>
[...]
</issueCompacts>


我使用这个XML,它实际上包含五个问题,并从中创建一个名为$ issuesObj的SimpleXMLElement对象(请注意复数“问题”)。然后,我遍历这些问题:

foreach ($issuesObj as $issueObj) {
[...]
} //foreach


在此循环内(请注意as变量的单数“问题”),如果我var_dump()$ issueObj,则会得到以下信息:

object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["id"]=>
string(4) "XX-1"
}
["field"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#16 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
[1]=>
object(SimpleXMLElement)#17 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(7) "Bill-to"
}
["value"]=>
string(3) "NBS"
}
}
}


这是$ issueObj-> asXml()的转储:

<?xml version="1.0"?>
<issue id="XX-1">
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>Bug</value>
</field>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Bill-to">
<value>NBS</value>
</field>
</issue>


到目前为止,这完全符合预期。但是,这就是奇怪的地方。我想选择名称为“类型”的问题中的字段,所以我使用了xpath()方法:

$typeField = $issueObj->xpath('//field[@name="Type"]')


现在,如果我转储$ typeField,则会得到以下信息:

array(5) {
[0]=>
object(SimpleXMLElement)#10 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
[1]=>
object(SimpleXMLElement)#11 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(11) "New Feature"
}
[2]=>
object(SimpleXMLElement)#13 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(11) "New Feature"
}
[3]=>
object(SimpleXMLElement)#14 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
[4]=>
object(SimpleXMLElement)#15 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(11) "New Feature"
}
}


请注意,有五个元素,而不是预期的两个。似乎正在发生的事情是xpath()方法作用于原始的$ issuesObj,而不作用于作为子集的$ issueObj。但是,它变得更加奇怪。如果我将$ issueObj转换为XML,然后使用该XML直接返回一个对象,那么它将起作用。从而:

$issueObj = new \SimpleXMLElement($issueObj->asXml());
$typeField = $issueObj->xpath('//field[@name="Type"]');
var_dump($typeField); exit;


产生这个:

array(1) {
[0]=>
object(SimpleXMLElement)#17 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
}


哪个是正确的。并调用$ typeField [0]-> asXml()现在会产生以下结果:

<?xml version="1.0"?>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>Bug</value>
</field>


同样,这完全符合预期。

关于SimpleXMLElement为什么采用这种方式的任何线索?

最佳答案

问题在于XPath如何处理上下文。 This page on MSDN尽管显然是在谈论完全不同的实现,但它有一个简洁的解释:


使用双正斜杠(//)的表达式表示可以包含零个或多个层次结构的搜索。当此运算符出现在模式的开头时,上下文是相对于文档根目录的。


因此,foo//bar从“当前”节点开始,找到名为foo的子代,然后递归地在其子代中搜索bar;但是//bar跳到文档的顶部,并递归搜索所有称为bar的节点。

要显式引用当前上下文,可以使用.,因此.//field[@name="Type"]应该可以根据需要工作。

由于在您的情况下,field元素是当前节点的直接子元素,因此无论如何您都不需要递归//,因此./field[@name="Type"]field[@name="Type"]也应该起作用。



附加说明:标题中的短语“不在对象中”表明您正在考虑将SimpleXML转换为一堆PHP对象。事实并非如此;而是将SimpleXML视为用于处理内存中已解析的XML文档的API,并将每个SimpleXMLElement视为指向该已解析文档的指针。该API旨在在PHP中感觉“自然”,但比大多数PHP对象包含更多的“魔术”。

关于php - SimpleXMLElement-> xpath()显示不在对象中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19601771/

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