DOM XML 字符串替换错误
DOM XML string replace bug
谁能解释一下 PHP 中的这种奇怪情况?这是例子。
我有字符串:"Olbrachtova 10"。我想在数字前添加逗号并在逗号前删除 space 。所以结果会是。
"Olbrachtova, 10"
这个字符串需要写在XML中,我正在使用DOMDocument库。
我正在使用此代码:
查找第一个数字位置的函数(效果很好):
private function findOffset($text){
preg_match('/^\D*(?=\d)/', $text, $m);
return isset($m[0]) ? strlen($m[0]) : false;
}
将字符插入字符串的功能(也很好用)
private function stringInsert($str,$insertstr,$pos)
{
$str = substr($str, 0, $pos) . $insertstr . substr($str, $pos);
return $str;
}
这是最后的剧本
//string to change
$address = "Olbrachtova 10";
//position of first number
$numberPosition = $this->findOffset($address);
if ($numberPosition){
//remove space before number if exists
if($address[$numberPosition - 1] == ' '){
//remove space - HERE IS PROBLEM
$address[$numberPosition - 1] = '';
//find new position of number
$numberPosition = $this->findOffset($address);
}
//add comma before number
$address = $this->stringInsert($address,", ",$numberPosition);
}else{
//if string has no number return false - is invalid
return false;
}
在此处理之后,我试图将 "Olbrachtova, 10" 的最终字符串附加到 XML。
var_dump($address);
//return
string(15) "Olbrachtova, 10"
这是要追加的最后一行
$parcel->appendChild($xml->createElement("Indirizzo", $address));
这个输出是:
<Indirizzo>Olbrachtova</Indirizzo>
它总是在逗号前换行,在我用
删除space的地方
$address[$numberPosition - 1] = '';
为什么?
但是当我使用它来删除 space
$address = substr_replace($address,'',$numberPosition - 1,1);
一切正常。谁能解释一下为什么第一种方法不起作用?
编辑
这是完整的代码
<?php
function findOffset($text){
preg_match('/^\D*(?=\d)/', $text, $m);
return isset($m[0]) ? strlen($m[0]) : false;
}
function stringInsert($str,$insertstr,$pos)
{
$str = substr($str, 0, $pos) . $insertstr . substr($str, $pos);
return $str;
}
$xml = $dom = new DOMDocument('1.0', 'UTF-8');
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
//main element for soap request
$mainSection = $xml->createElement("Info");
$parcel = $xml->createElement("Parcel");
//string to change
$address = "Olbrachtova 10";
//position of first number
$numberPosition = findOffset($address);
if ($numberPosition){
//remove space before number if exists
if($address[$numberPosition - 1] == ' '){
//remove space - HERE IS PROBLEM
$address[$numberPosition - 1] = '';
//find new position of number
$numberPosition = findOffset($address);
}
//add comma before number
$address = stringInsert($address,", ",$numberPosition);
}else{
//if string has no number return false - is invalid
return false;
}
$parcel->appendChild($xml->createElement("Indirizzo", $address));
var_dump($address);
//append Package
$mainSection->appendChild($parcel);
//append whole xml to main
$xml->appendChild($mainSection);
$output = $xml->saveXML();
print_r($output);
?>
您可以在这里进行测试:http://phptester.net/
将示例分解为具有静态字符串的 DOM 函数。尝试重现。也许你在那之前有一个错误。另外不要使用 DOMDocument::createElement()
的第二个参数——它不是 DOM 标准的一部分。这里有一个可以打破XML的bug。它不应该由您提供的示例触发,但创建文本节点并附加它更安全。
$document = new DOMDocument();
$document
->appendChild($document->createElement("Indirizzo"))
->appendChild($document->createTextNode("Olbrachtova, 10"));
echo $document->saveXml();
输出:
<?xml version="1.0"?>
<Indirizzo>Olbrachtova, 10</Indirizzo>
问题是您将空字符串 ""
分配给了字符串索引。这导致在该位置写入 NULL 字节。来自 PHP 关于 strings 的手册:
Warning
Writing to an out of range offset pads the string with spaces. Non-integer types are converted to integer. Illegal offset type emits E_NOTICE. Negative offset emits E_NOTICE in write but reads empty string. Only the first character of an assigned string is used. Assigning empty string assigns NULL byte.
并且 NULL 字节在 C/C++ 内部标记字符串的结尾。这就是为什么 createElement
方法只在 XML 元素中写入值 "Olbrachtova",而不管 php.
中的字符串是什么样子的
解决方法:任何情况下都不要写$string[$index] = "";
谁能解释一下 PHP 中的这种奇怪情况?这是例子。
我有字符串:"Olbrachtova 10"。我想在数字前添加逗号并在逗号前删除 space 。所以结果会是。
"Olbrachtova, 10"
这个字符串需要写在XML中,我正在使用DOMDocument库。
我正在使用此代码:
查找第一个数字位置的函数(效果很好):
private function findOffset($text){
preg_match('/^\D*(?=\d)/', $text, $m);
return isset($m[0]) ? strlen($m[0]) : false;
}
将字符插入字符串的功能(也很好用)
private function stringInsert($str,$insertstr,$pos)
{
$str = substr($str, 0, $pos) . $insertstr . substr($str, $pos);
return $str;
}
这是最后的剧本
//string to change
$address = "Olbrachtova 10";
//position of first number
$numberPosition = $this->findOffset($address);
if ($numberPosition){
//remove space before number if exists
if($address[$numberPosition - 1] == ' '){
//remove space - HERE IS PROBLEM
$address[$numberPosition - 1] = '';
//find new position of number
$numberPosition = $this->findOffset($address);
}
//add comma before number
$address = $this->stringInsert($address,", ",$numberPosition);
}else{
//if string has no number return false - is invalid
return false;
}
在此处理之后,我试图将 "Olbrachtova, 10" 的最终字符串附加到 XML。
var_dump($address);
//return
string(15) "Olbrachtova, 10"
这是要追加的最后一行
$parcel->appendChild($xml->createElement("Indirizzo", $address));
这个输出是:
<Indirizzo>Olbrachtova</Indirizzo>
它总是在逗号前换行,在我用
删除space的地方$address[$numberPosition - 1] = '';
为什么?
但是当我使用它来删除 space
$address = substr_replace($address,'',$numberPosition - 1,1);
一切正常。谁能解释一下为什么第一种方法不起作用?
编辑
这是完整的代码
<?php
function findOffset($text){
preg_match('/^\D*(?=\d)/', $text, $m);
return isset($m[0]) ? strlen($m[0]) : false;
}
function stringInsert($str,$insertstr,$pos)
{
$str = substr($str, 0, $pos) . $insertstr . substr($str, $pos);
return $str;
}
$xml = $dom = new DOMDocument('1.0', 'UTF-8');
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
//main element for soap request
$mainSection = $xml->createElement("Info");
$parcel = $xml->createElement("Parcel");
//string to change
$address = "Olbrachtova 10";
//position of first number
$numberPosition = findOffset($address);
if ($numberPosition){
//remove space before number if exists
if($address[$numberPosition - 1] == ' '){
//remove space - HERE IS PROBLEM
$address[$numberPosition - 1] = '';
//find new position of number
$numberPosition = findOffset($address);
}
//add comma before number
$address = stringInsert($address,", ",$numberPosition);
}else{
//if string has no number return false - is invalid
return false;
}
$parcel->appendChild($xml->createElement("Indirizzo", $address));
var_dump($address);
//append Package
$mainSection->appendChild($parcel);
//append whole xml to main
$xml->appendChild($mainSection);
$output = $xml->saveXML();
print_r($output);
?>
您可以在这里进行测试:http://phptester.net/
将示例分解为具有静态字符串的 DOM 函数。尝试重现。也许你在那之前有一个错误。另外不要使用 DOMDocument::createElement()
的第二个参数——它不是 DOM 标准的一部分。这里有一个可以打破XML的bug。它不应该由您提供的示例触发,但创建文本节点并附加它更安全。
$document = new DOMDocument();
$document
->appendChild($document->createElement("Indirizzo"))
->appendChild($document->createTextNode("Olbrachtova, 10"));
echo $document->saveXml();
输出:
<?xml version="1.0"?>
<Indirizzo>Olbrachtova, 10</Indirizzo>
问题是您将空字符串 ""
分配给了字符串索引。这导致在该位置写入 NULL 字节。来自 PHP 关于 strings 的手册:
Warning Writing to an out of range offset pads the string with spaces. Non-integer types are converted to integer. Illegal offset type emits E_NOTICE. Negative offset emits E_NOTICE in write but reads empty string. Only the first character of an assigned string is used. Assigning empty string assigns NULL byte.
并且 NULL 字节在 C/C++ 内部标记字符串的结尾。这就是为什么 createElement
方法只在 XML 元素中写入值 "Olbrachtova",而不管 php.
解决方法:任何情况下都不要写$string[$index] = "";