DOM XML字符串替换bug

时间:2016-05-08 10:57:44

标签: php xml string domdocument

有人可以用PHP解释这种奇怪的情况吗?这是一个例子。

我有字符串:“Olbrachtova 10”。我想在数字之前添加逗号并在逗号之前删除空格。结果就是。

“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>

它总是在逗号之前断开,在我用

删除空格的地方
$address[$numberPosition - 1] = '';

WHY吗

但是当我使用它来移除空间时

$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/

2 个答案:

答案 0 :(得分:2)

问题是您将空字符串""分配给字符串索引。这导致在该位置写入NULL字节。从关于strings的PHP手册:

  

警告   写入超出范围的偏移量填充带有空格的字符串。非整数类型转换为整数。非法偏移类型会发出 E_NOTICE 。负偏移在写入时发出 E_NOTICE ,但读取空字符串。仅使用指定字符串的第一个字符。分配空字符串会指定NULL字节。

NULL字节在内部标记C / C ++中字符串的结尾。这就是为什么createElement方法只写出值&#34; Olbrachtova&#34;在XML元素中,无论字符串在php中是什么样的。

解决方案:在任何情况下都不要写$string[$index] = "";

答案 1 :(得分:0)

使用静态字符串将示例分解为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>