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] = "";