使用 PHP 替换 xml/plist 文件中的字符串
Posted
技术标签:
【中文标题】使用 PHP 替换 xml/plist 文件中的字符串【英文标题】:Replacing a string in an xml/plist file using PHP 【发布时间】: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 值/字符串一样不想让对方受其影响,有可能吗?
【问题讨论】:
【参考方案1】:不确定标题的回显是如何工作的,但在这段代码中,我使用 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);
【讨论】:
好的,这行得通,但它改变了两个 .plist 文件的标题,我认为那是因为我使用 *.plist,我该怎么办? 这是我的问题的一部分。 我将其中一个标题更改为 test 并将 $titleToUpdate = "Correct Title2"; 更改为 $titleToUpdate = "test "; 但它并没有改变文件中的标题,我错过了什么吗?顺便说一句,如果我的 Q 不够清楚,对不起:(我不确定是否了解所有内容,但您可以使用 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->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";
【讨论】:
以上是关于使用 PHP 替换 xml/plist 文件中的字符串的主要内容,如果未能解决你的问题,请参考以下文章