以下是xml文件中的示例位:
<array>
<dict>
<key>Name</key>
<string>Joe Smith</string>
<key>Type</key>
<string>Profile</string>
<key>Role</key>
<string>User</string>
<key>Some Number</key>
<integer>1</integer>
<key>Some Boolean</key>
<true/>
</dict>
</array>
我有两个不同的目标。第一种是从dict
节点中提取一个看起来像的数组:
[Name] => Joe Smith
[Type] => Profile
[Role] => User
[Some Number] => 1
[Some Boolean] => true
包含布尔值并不重要,所以如果这增加了太多的复杂性,我宁愿知道如何处理其他人。
第二个目标是能够选择值节点(<string>
,<integer>
等),以便我可以更改值。我知道我需要根据前面关键元素的文本值选择它。
我认为以下XPath应该有效:
//key[.=$keyname]/following-sibling[1]
但我不确定。
基本上,Apple使用的整个系统看似合乎逻辑,但完全违背了我对XML应该如何工作的理解。如果我运行世界,原始XML看起来更像:
<dict type="array">
<value key="Name" type="string">Joe Smith</value>
<value key="Type" type="string">Profile</value>
<value key="Role type="string">User</value>
<value key="Some Number" type="integer">1</value>
<value key="Some Boolean" type="boolean">true</value>
</dict>
但由于这是合乎逻辑的,我想知道我是否遗漏了一些明显的处理方式。
答案 0 :(得分:3)
那个xpath选择器看起来对我来说没问题。你可能想要检查你检索的兄弟的值,看看它是你想要改变的标签(在布尔情况下)还是元素的值。
在将数据提取到数组方面,类似于...
$xml = new SimpleXMLElement($data);
$output = array();
$key = null;
$value = null;
foreach ($xml->dict->children() as $child) {
if ($child->getName() == 'key') {
$key = (string)$child;
} elseif (!is_null($key)) {
$childStr = (string)$child;
$value = (empty($childStr) ? $child->getName() : $childStr);
}
if (!is_null($key) && !is_null($value)) {
$output[$key] = $value;
$key = null;
$value = null;
}
}
var_dump($output);
......应该根据我的理解做你正在寻找的事情。
詹姆斯
答案 1 :(得分:1)
您可以使用
/plist/dict/key[.='Name']/following-sibling::*[1]
选择字符串节点“Joe Smith”并相应地更新它。
我使用XPath更新XML文件的PHP代码如下所示:
function updateNodesByXPath($xmlin, $expression, $value) {
$dom = new DOMDocument();
$dom->preserveWhiteSpace = true;
$dom->formatOutput = false;
$dom->loadXML($xmlin);
$xpath = new DOMXPath($dom);
$elements = $xpath->query($expression);
foreach ($elements as $element) {
$element->nodeValue = $value;
}
$xmlout = $dom->saveXML($dom, LIBXML_NOEMPTYTAG);
// Add XML header when present before (DOMDocument::saveXML will remove it)
if (strncasecmp($xmlin, '<?xml', 5)) {
$xmlout = preg_replace('~<\?xml[^>]*>\s*~sm', '', $xmlout);
}
return $xmlout;
}