替换部分 XML 节点值


Replace part of XML node value

我正在尝试用另一个值替换xml节点值的一部分。例如,我的 xml 中有这个节点:

<eerste_kwartier>naam leeg</eerste_kwartier>

或例如:

<eerste_kwartier>leeg leeg</eerste_kwartier>

在第一个示例中,我想用其他值替换"leeg"值。在第二个中,我只想用其他东西替换第一个"leeg"值。任何想法我应该怎么做?

提前感谢,

扬·蒂门

正确的方法是使用 PHP 的 DOMDocument 类来提取你需要的东西。这是一个可行的解决方案:

$str = '<eerste_kwartier>naam leeg</eerste_kwartier>';
$doc = new DOMDocument();
$fragment = $doc->createDocumentFragment();
$fragment->appendXML( $str);
$doc->appendChild( $fragment);
$xpath = new DOMXPath( $doc);
$node = $xpath->query( '/eerste_kwartier')->item(0);
$text = $doc->createTextNode( $node->textContent);
$node->nodeValue = ''; // Clear out the contents of the tag
// Get the text before and after the replacement
$start = strpos( $text->wholeText, 'leeg');
$before = $text->substringData( 0, $start);
$after = $text->substringData( $start + strlen( 'leeg'), strlen( $text->wholeText));
// Put the text back, minus the replacement, with something else added
$node->appendChild( $doc->createTextNode( trim( $before)));
$node->appendChild( $doc->createTextNode( "Something Else"));
$node->appendChild( $doc->createTextNode( $after));
echo htmlentities( $doc->saveXML());

这输出:

<?xml version="1.0"?> <eerste_kwartier>naam Something Else</eerste_kwartier> 

对于第二个测试用例,它将输出:

<?xml version="1.0"?> <eerste_kwartier>Something Else leeg</eerste_kwartier> 

基本上,你可以使用 DOM 使用 PHP 来实现这一点。

给定字符串中的 XML 格式,如下所示:

    $xml = <<<EOX
<root>    
  <eerste_kwartier>naam leeg</eerste_kwartier>
  <eerste_kwartier>leeg leeg</eerste_kwartier>
</root>
EOX;

您可以执行以下操作:

1 - 使用 PHP 和 DOM

使用 DOM,您可以使用 getElementsByTagName() 方法获取具有相同标记名称的元素列表,遍历该列表并应用您喜欢的文本转换。

例:

// Load source XML
$xmlObj = new DOMDocument("1.0", "UTF-8");
$xmlObj->loadXML($xml);
// Obtain interesting nodes into a node list object
$nodeList = $xmlObj->getElementsByTagName('eerste_kwartier');
// Prepare destination XML object
$xmlObjResult = new DOMDocument("1.0", "UTF-8");
$rootElement = $xmlObjResult->createElement("root");
// Walk node list
for ($i = 0; $i < $nodeList->length; $i++) {
  $tmp = $nodeList->item($i)->nodeValue;
  // Use regular expressions for greater flexibility in selecting text to replace
  $tmp = preg_replace('/naam/', 'leeg', $tmp);
  // Prepare destination element
  $eerste_kwartier = $xmlObjResult->createElement("eerste_kwartier");
  $cdata = $xmlObjResult->createCDATASection($tmp);
  $eerste_kwartier->appendChild($cdata);
  $rootElement->appendChild($eerste_kwartier);
}
// Append root element to the document
$xmlObjResult->appendChild($rootElement);
// Enjoy your XML
echo $xmlObjResult->saveXML();

2 - 使用 PHP 和 DOMXPath

上面的例子可以很容易地更改为使用 XPath 的 query() 而不是 DOM 的 getElementsByTagName()。

所以你会做:

// Load source XML
$xmlObj = new DOMDocument("1.0", "UTF-8");
$xmlObj->loadXML($xml);
// Obtain interesting nodes into a node list object
$xpath = new DOMXPath($xmlObj);
$nodeList = $xpath->query("//eerste_kwartier");
// Prepare destination XML object
$xmlObjResult = new DOMDocument("1.0", "UTF-8");
$rootElement = $xmlObjResult->createElement("root");
// Walk node list
for ($i = 0; $i < $nodeList->length; $i++) {
  $tmp = $nodeList->item($i)->nodeValue;
  // Use regular expressions for greater flexibility in selecting text to replace
  $tmp = preg_replace('/naam/', 'leeg', $tmp);
  // Prepare destination element
  $eerste_kwartier = $xmlObjResult->createElement("eerste_kwartier");
  $cdata = $xmlObjResult->createCDATASection($tmp);
  $eerste_kwartier->appendChild($cdata);
  $rootElement->appendChild($eerste_kwartier);
}
// Append root element to the document
$xmlObjResult->appendChild($rootElement);
// Enjoy your XML
echo $xmlObjResult->saveXML();

结论

正如您肯定已经注意到的那样,这两个选项非常相似。

如果您在文档中的搜索解析为搜索相同的标签名称,我建议使用选项 1;如果您的搜索应该比这更清晰,我建议选项 2,因为 XPath 有很多很好的武器来对抗 XML 搜索的复杂性(可以在此处找到对 XPath 的简要介绍, 但是有很多可用的材料只是谷歌搜索)。

我不会让 XSL 进入图片,除非你应该应用更高的规模和清晰的内容转换,但以防万一:http://htmlite.com/XML008.php(一个非常简短的 XSLT 介绍教程,应该会让你胃口大开)。

你不能

使用str_replace函数吗?

$xml = str_replace('<eerste_kwartier>leeg leeg</eerste_kwartier>','<eerste_kwartier>somethingelse leeg</eerste_kwartier>',$xml);