Reputation: 1026
Can anybody explain this weird situation in PHP? Here is example.
I have string: "Olbrachtova 10". I want to add comma before number and remove space before comma. So result will be.
"Olbrachtova, 10"
This string needs to be written in XML and I am using DOMDocument library.
I am using this code:
Function to find position of first number (works well):
private function findOffset($text){
preg_match('/^\D*(?=\d)/', $text, $m);
return isset($m[0]) ? strlen($m[0]) : false;
}
Funtion to insert character into string (works well too)
private function stringInsert($str,$insertstr,$pos)
{
$str = substr($str, 0, $pos) . $insertstr . substr($str, $pos);
return $str;
}
And here is final script
//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;
}
After this processing I am trying to append final string which is "Olbrachtova, 10" to XML.
var_dump($address);
//return
string(15) "Olbrachtova, 10"
And here is final line to append
$parcel->appendChild($xml->createElement("Indirizzo", $address));
Output of this is:
<Indirizzo>Olbrachtova</Indirizzo>
It always break before comma, in the place where i removed space with
$address[$numberPosition - 1] = '';
WHY?
But when i am using this to remove space
$address = substr_replace($address,'',$numberPosition - 1,1);
Everything works great. Can anybody explain why the first method didn't work?
EDIT
Here is full code
<?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);
?>
And you can test it here: http://phptester.net/
Upvotes: 0
Views: 66
Reputation: 19546
The problem is that you assign the empty string ""
to a string index. This results in the NULL byte being written at that location. From the PHP manual about 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.
And the NULL byte marks the end of a string in C/C++ internally. So thats why the createElement
method only writes the value "Olbrachtova" in the XML element, regardless of what the string looks like in php.
Solution: Do not write $string[$index] = "";
under any circumstances
Upvotes: 2
Reputation: 19482
Break the example down to the DOM functions with static strings. Try to reproduce. Maybe you have an error before that. Additionally do not use the second argument of DOMDocument::createElement()
- it is not part of the DOM standard. Here is a bug that can break the XML. It should not be triggered by the example you provided, but it is safer to create the text node and append it.
$document = new DOMDocument();
$document
->appendChild($document->createElement("Indirizzo"))
->appendChild($document->createTextNode("Olbrachtova, 10"));
echo $document->saveXml();
Output:
<?xml version="1.0"?>
<Indirizzo>Olbrachtova, 10</Indirizzo>
Upvotes: 0