使用 PHP 替换 xml/plist 文件中的字符串

Replacing a string in an xml/plist file using PHP

我在一个目录中有两个 .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>

我得到了标题的value/string:

$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 的 value/string,就像我更改 title 一样 value/string 其中一个我不希望另一个受到影响,可以吗?

我不确定是否理解所有内容,但您可以使用 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")

不确定标题的回显是如何工作的,但在这段代码中,我使用 XPath 找到了内容为 title<key> 元素。然后它获取以下 <string> 元素的值。

要更新它,您可以在 SimpleXML 中稍作改动,使其设置 <string> 元素的值,然后将结果 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);
}

虽然不漂亮,但很管用。

$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();

也可以将 Xpath 与 DOM 一起使用。

$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";
    }
}