【问题标题】:Replacing a string in an xml/plist file using PHP使用 PHP 替换 xml/plist 文件中的字符串
【发布时间】:2019-12-27 19:24:36
【问题描述】:

我在一个目录中有两个.plist 文件,它们看起来都像这样:

<dict>
    <key>bundle-identifier</key>
    <string>TEXT</string>
    <key>bundle-version</key>
    <string>VESRION</string>
    <key>kind</key>
    <string>software</string>
    <key>subtitle</key>
    <string>TEXT</string>
    <key>title</key>
    <string>TEXT</string>
  </dict>

我能够通过以下方式获得 title 的值/字符串:

$files = array();
foreach (glob("../../plists/*.plist") as $file) {
    $files[] = $file;
    //echo "$file";

    $fileContent = file_get_contents($file);
    $xml = simplexml_load_string($fileContent) or die("Error: Cannot create object");
    $resultNames = $xml->dict->array->dict->dict->string[4] . '<br /> <br />';
    //echo $resultNames;

}

现在我想用 php 为它们中的每一个更改 title 的值/字符串,就像我更改其中一个的 title 值/字符串一样不想让对方受其影响,有可能吗?

【问题讨论】:

    标签: php xml plist


    【解决方案1】:

    不确定标题的回显是如何工作的,但在这段代码中,我使用 XPath 来查找具有内容 title 的 &lt;key&gt; 元素。然后它获取以下&lt;string&gt; 元素的值。

    要更新它,您可以在 SimpleXML 中稍加修改,使其设置 &lt;string&gt; 元素的值,然后将结果 XML 保存回相同的文件名......

    $xml = simplexml_load_string($fileContent) or die("Error: Cannot create object");
    // Find the correct string element from the preceding key for title
    $titleString = $xml->xpath('//key[.="title"]/following-sibling::string')[0];
    
    // Set new value
    $titleString[0] = "new Title1";
    // Save the file
    $xml->asXML($file);
    

    如果您通过文件名识别内容,则检查$file,但如果您只能通过标题识别它,那么您需要检查这是否找到了您想要的标题。

    $titleToUpdate = "Correct Title2";
    $fileContent = file_get_contents($file);
    $xml = simplexml_load_string($fileContent) or die("Error: Cannot create object");
    $titleString = $xml->xpath('//key[.="title"]/following-sibling::string[.="'.$titleToUpdate.'"]');
    
    
    // Check there is 1 matching item
    if ( count($titleString) == 1 )  {
        $titleString[0][0] = "new Title12";
        $xml->asXML($file);
    }
    

    【讨论】:

    • 好的,这行得通,但它改变了两个 .plist 文件的标题,我认为那是因为我使用 *.plist,我该怎么办?
    • 这是我的问题的一部分。
    • 我将其中一个标题更改为 test 并将 $titleToUpdate = "Correct Title2"; 更改为 $titleToUpdate = "test "; 但它并没有改变文件中的标题,我错过了什么吗?顺便说一句,如果我的 Q 不够清楚,对不起:(
    • titleTEXT 将 TEXT 更改为 test
    【解决方案2】:

    我不确定是否了解所有内容,但您可以使用 DomDocument 更改值。

    $doc = new DOMDocument;
    $doc->load('your_xml_file.xml');
    
    $elements = $doc->getElementsByTagName("string");
    
    foreach ($elements as $element) {
       //$element->nodeName will be "string"
       $nodes = $element->childNodes;
    
       foreach ($nodes as $node) {
          $node->nodeValue = 'New value';
        }
    }
    
    $doc->save("newfile.xml")
    

    【讨论】:

    • 这可能有效,但如果不知道确切的文件名怎么办?我可以使用 glob 吗?
    • 您可以像这样使用字符串变量:doc-&gt;loadXML($string_variable_that_content_your_xml); 如果您的变量不包含有效的 XML,它将返回 false,因此您应该检查返回值。
    【解决方案3】:

    它不漂亮,但很有效。

    $doc = new DOMDocument;
    $doc->load('file_address');
    
    $elements = $doc->documentElement;
    
    $found = false;
    foreach ($elements->childNodes AS $item) {
        if($found){
            $item->nodeValue = 'changed';
            $found = false;
        }else{
            if($item->nodeName == 'key' && $item->nodeValue == 'title'){
                $found = true;
            }
        }
    }
    $doc->saveXML();
    

    【讨论】:

      【解决方案4】:

      在 DOM 中使用 Xpath 也是可能的。

      $titleToUpdate = 'Original Title';
      
      $document = new DOMDocument();
      // load from string, for file: $document->load($fileName);
      $document->loadXML($xml);
      $xpath = new DOMXpath($document);
      
      $expression = '//dict/key[.="title"]/following-sibling::string[.="'.$titleToUpdate.'"]';
      
      $modified = FALSE; 
      foreach ($xpath->evaluate($expression) as $titleValueNode) {
          $titleValueNode->textContent = 'Changed Title';
          $modified = TRUE;
      }
      
      if ($modified) {
        // output string, to save file: $document->save($fileName);
        echo $document->saveXML();
      }
      

      输出:

      <?xml version="1.0"?>
      <dict>
          <key>bundle-identifier</key>
          <string>TEXT</string>
          <key>bundle-version</key>
          <string>VESRION</string>
          <key>kind</key>
          <string>software</string>
          <key>subtitle</key>
          <string>TEXT</string>
          <key>title</key>
          <string>Changed Title</string>
      </dict>
      

      这种方法会更改任何匹配的项目,并只存储它修改过的一个或多个。

      现在,如果您确实需要为此查找不同的文件,我建议您将操作移至函数中。

      function replaceTitle(string $fileName, string $title): bool {
          // the actual action from the example
          return $modified;
      }
      
      $files = new GlobIterator(__DIR__.'/path/*.plist');
      foreach ($files as $file) {
          if (replaceTitle((string)$file, 'Original Title')) {
              echo "Modified: $file\n";
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-09-07
        • 2012-08-07
        • 2011-01-10
        • 1970-01-01
        • 2013-01-13
        • 2021-01-02
        • 1970-01-01
        • 1970-01-01
        • 2013-06-13
        相关资源
        最近更新 更多