代码之家  ›  专栏  ›  技术社区  ›  Anthony

使用php中的simplexml从plist样式xml获取键/值对

  •  3
  • Anthony  · 技术社区  · 14 年前

    以下是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]
    

    但我不确定。

    基本上,苹果使用的整个系统看起来很合乎逻辑,但与我对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>
    

    但由于这是相当合乎逻辑的,我想知道我是否遗漏了一些明显的处理方法。

    2 回复  |  直到 13 年前
        1
  •  3
  •   jstephenson    14 年前

    对于我来说,这个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);
    

    …应该按照我的理解去做你想要的。

    詹姆斯

        2
  •  1
  •   skettler    13 年前

    你可以使用

    /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;
    }