PHP SimpleXML :: addChild с пустой строкой - избыточный узел - PullRequest
3 голосов
/ 29 октября 2008

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

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

[description] => !4jh5jh1uio4jh5ij14j34io5j!

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

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

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

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

Ответы [ 4 ]

1 голос
/ 09 апреля 2009

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

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

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

1 голос
/ 03 ноября 2008

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

$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).

0 голосов
/ 03 января 2009

Я создал библиотеку 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/

0 голосов
/ 29 октября 2008

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

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

...