PHP SimpleXML::addChild с пустой строкой — избыточный узел

Вызов addChild с пустой строкой в ​​качестве значения (или даже с пробелом), по-видимому, приводит к добавлению избыточного узла SimpleXml внутри узла вместо добавления только узла без значения.

Вот краткая демонстрация того, что происходит:

[description] => !4jh5jh1uio4jh5ij14j34io5j!

А вот с пустой строкой:

[description] => SimpleXMLElement Object ( [0] => ) 

Обходной путь, который я использую на данный момент, довольно ужасен — я делаю str_replace в окончательном JSON, чтобы заменить !4jh5jh1uio4jh5ij14j34io5j! с пустой строкой. Фу. Возможно, единственный ответ на данный момент — «отправить отчет об ошибке в simplexml»…

У кого-нибудь есть лучшее решение?


person Dave    schedule 29.10.2008    source источник


Ответы (4)


Кажется, я понял, что происходит. Дан такой код:

$xml = new SimpleXMLElement('<xml></xml>');
$xml->addChild('node','value');
print_r($xml);

$xml = new SimpleXMLElement('<xml></xml>');
$xml->addChild('node','');
print_r($xml);

$xml = new SimpleXMLElement('<xml></xml>');
$xml->addChild('node');
print_r($xml);

Вывод таков:

SimpleXMLElement Object
(
    [node] => value
)
SimpleXMLElement Object
(
    [node] => SimpleXMLElement Object
        (
            [0] => 
        )

)
SimpleXMLElement Object
(
    [node] => SimpleXMLElement Object
        (
        )

)

Итак, чтобы сделать так, чтобы в случае № 2 пустой элемент не создавался (т.е. если вы не знаете, будет ли второй аргумент пустой строкой или нет), вы можете просто сделать что-то вроде этого:

$mystery_string = '';

$xml = new SimpleXMLElement('<xml></xml>');
if (preg_match('#\S#', $mystery_string)) // Checks for non-whitespace character
  $xml->addChild('node', $mystery_string);
else
  $xml->addChild('node');

print_r($xml);
echo "\nOr in JSON:\n";
echo json_encode($xml);

Для вывода:

SimpleXMLElement Object
(
    [node] => SimpleXMLElement Object
        (
        )

)

Or in JSON:
{"node":{}}

Это то, что вы хотите?

Лично я никогда не использую SimpleXML, и не только из-за такого странного поведения — он все еще находится в стадии разработки, а в PHP5 отсутствует около 2/3 методов, необходимых для манипуляций с DOM (например, deleteChild, replaceChild и т. д.). .

Я использую DOMDocument (стандартизированный, быстрый и многофункциональный, поскольку это интерфейс к libxml2).

person joelhardi    schedule 03.11.2008

С SimpleXML то, что вы получаете, если используете print_r() или var_dump(), serialize() или подобное, не соответствует тому, что хранится внутри объекта. Это «магический» объект, который перегружает способ взаимодействия PHP со своим содержимым.

Вы получаете истинное представление элемента только с помощью AsXML().

Когда что-то вроде print_r() перебирает элемент SimpleXML или вы обращаетесь к его свойствам с помощью оператора ->, вы получаете измененную версию объекта. Эта измененная версия позволяет вам делать такие вещи, как "echo $xml->surname" или $xml->names[1], как если бы она действительно имела эти свойства, но отделена от истинного XML, содержащегося внутри: в элементах представления не обязательно по порядку, а элементы, имена которых являются зарезервированными словами PHP (например, «var»), не представлены как свойства, но к ним можно получить доступ с помощью кода, такого как $xml["var"] - как если бы объект был ассоциативным массивом . Если несколько одноуровневых элементов имеют одинаковое имя, они представлены как массивы. Я предполагаю, что пустая строка также представлена ​​​​как массив по какой-то причине. Однако при выводе с использованием AsXML() вы получаете реальное представление.

person thomasrutter    schedule 09.04.2009

Возможно, я неправильно понимаю вопрос, но мне кажется, что когда вы используете метод addChild, вам необходимо иметь строку в качестве аргумента для имени узла независимо от того, какой контент находится в узле. Значение (второй аргумент) является необязательным и может быть оставлено пустым, чтобы добавить и очистить узел.

Дайте мне знать, если это поможет.

person Stephen Walcher    schedule 29.10.2008

Я создал библиотеку Xml, которая расширяет объект simpleXml, чтобы включить все функциональные возможности, которые присутствуют в DOMDocument, но отсутствует интерфейс из SimpleXml (поскольку две функции взаимодействуют с одним и тем же базовым объектом libxml2 — по ссылке). У него также есть тонкости, такие как AsArray() или AsJson() для вывода вашего объекта в одном из этих форматов.

Я только что обновил библиотеку, чтобы она работала так, как вы ожидаете, при выводе JSON. Вы можете сделать следующее:

$xml = new bXml('<xml></xml>');
$xml->addChild('node', '');
$json_w_root = $xml->asJson(); // is { 'xml': {'node':'' } }
$json = $xml->children()->asJson(); // is { 'node' : '' } as expected.

Библиотека размещена в коде Google по адресу http://code.google.com/p/blibrary/<. /а>

person null    schedule 03.01.2009
comment
Хитрость заключается в том, чтобы преобразовать объект simpleXML в массив перед кодированием JSON. - person null; 03.01.2009