Примушування об’єкта SimpleXML до рядка, незалежно від контексту


78

Скажімо, у мене є такий XML

<channel>
  <item>
    <title>This is title 1</title>
  </item>
</channel>

Код нижче робить те, що я хочу, оскільки виводить заголовок у вигляді рядка

$xml = simplexml_load_string($xmlstring);
echo $xml->channel->item->title;

Ось моя проблема. У наведеному нижче коді заголовок не трактується як рядок у цьому контексті, тому в результаті замість рядка в масиві з’являється об’єкт SimpleXML.

$foo = array( $xml->channel->item->title );

Я працював над цим так

$foo = array( sprintf("%s",$xml->channel->item->title) );

але це здається потворним.

Який найкращий спосіб примусити об’єкт SimpleXML до рядка, незалежно від контексту?


Я подав кілька запитів до PHP, щоб реалізувати щось подібне SOAP_SINGLE_ELEMENT_ARRAYS для цього, і закликав би інших зробити те саме. SOAP_SINGLE_ELEMENT_ARRAYS змушує елементи, які / можуть / містять більше одного рядка, завжди аналізуватися як лише рядки. Звичайно, як згадали інші, вам потрібно знати, що ви повертаєте, але раз за разом я стикався з проблемами .NET SOAP-серверів, які WSDL для (за замовчуванням .NET за замовчуванням .NET) прототипував кожен рядок як змішаний або масив рядків. Замість current () 'ing або typecasting, біт просто повертає рядок
conrad10781

Відповіді:


151

Введіть команду SimpleXMLObject у рядок:

$foo = array( (string) $xml->channel->item->title );

Вищезазначений код внутрішньо викликає __toString()SimpleXMLObject. Цей метод не є загальнодоступним, оскільки він заважає схемі зіставлення об’єкта SimpleXMLObject, але його все одно можна викликати вищевказаним способом.


Це чистіше, ніж використання спринту. Мені це подобається
Mark Biek

5
Зверніть увагу, що використання функції, яка приймає рядкові аргументи, автоматично виконує кастинг цього типу (наприклад, echo, str_replace, substr).
Росс

3
$ foo = (рядок) $ xml-> channel-> item-> title; це те, що я шукав, оскільки мені не потрібен масив. Дякую.
Дразісіль

1
+100 ти щойно зробив мій вечір! Я новачок у SimpleXMLObject. Вари, які я витягував із нього, чудово «друкували» на екрані, але не виконували мого запиту до БД ... зітхання! З якого часу PHP був строго набраний? ;-)
megaSteve4

1
@ megaSteve4 "З якого часу PHP був строго набраний?" - це саме тому, що це не те, що це має статися: більшість функцій не мають визначеного контексту типу, тому не можуть неявно передавати цей тип. Звичайно, вони можуть явно відтворювати свої параметри введення, саме тому substrта ін. Хоча безпечніше робити акторський склад якомога раніше, щоб ви знали, що всі функції бачитимуть очікувані дані.
IMSoP

22

Ви можете використовувати функцію PHP

strval();

Ця функція повертає рядкові значення параметра, переданого їй.


3
@Mark Biek: Він працює над об'єктами, які __toString()реалізовані, і особливо в цьому випадку, він працює дуже добре з об'єктами типу SimpleXMLElement. Ви можете порівняти це з stringакторським складом у прийнятій відповіді. strval()є зручною функцією зворотного виклику, часто у поєднанні з array_map()та iterator_to_array($simpleXMLElement, false)або SimpleXMLElement::xpath().
hakre

9

Існує власний метод SimpleXML SimpleXMLElement :: asXML Залежно від параметра він записує SimpleXMLElement у файл xml 1.0 або просто у рядок:

$xml = new SimpleXMLElement($string);
$validfilename = '/temp/mylist.xml';
$xml->asXML($validfilename);    // to a file
echo $xml->asXML();             // to a string

Я отримую виклик невизначеної функції asXML, тому я здогадуюсь, що це зараз застаріло?
Еоін

1
@Eoin Хм ... Щойно перевірив мій приклад, він все ще чудово працює з власною установкою php 7.3
змішаний випадок

У них, мабуть, була інша проблема. Мої вибачення. Я виправив свою проблему зараз :)
Eoin,

3

Ще один потворний спосіб зробити це:

$foo = array( $xml->channel->item->title."" );

Це працює, але це не красиво.


3

Прийнята відповідь фактично повертає масив, що містить рядок, що не зовсім те, що запитував OP (рядок). Щоб розширити цю відповідь, використовуйте:

$foo = [ (string) $xml->channel->item->title ][0];

Що повертає єдиний елемент масиву, рядок.


2

Щоб отримати XML-дані у масив php, ви робите це:

// this gets all the outer levels into an associative php array
$header = array();
foreach($xml->children() as $child)
{
  $header[$child->getName()] = sprintf("%s", $child); 
}
echo "<pre>\n";
print_r($header);
echo "</pre>";

Щоб отримати дитину, тоді просто зробіть наступне:

$data = array();
foreach($xml->data->children() as $child)
{
  $header[$child->getName()] = sprintf("%s", $child); 
}
echo "<pre>\n";
print_r($data);
echo "</pre>";

Ви можете розширювати $ xml-> через кожен рівень, поки не отримаєте те, що хочете. Ви також можете помістити всі вузли в один масив без рівнів або майже будь-яким іншим способом, який ви хочете.



0

Не впевнений, чи змінили вони видимість __toString()методу з моменту написання прийнятої відповіді, але наразі це добре для мене працює:

var_dump($xml->channel->item->title->__toString());

ВИХІД:

string(15) "This is title 1"

0

Існує власний метод SimpleXML SimpleXMLElement :: asXML Залежно від параметра він записує SimpleXMLElement у файл xml 1.0, так

$get_file= read file from path;
$itrate1=$get_file->node;
$html  = $itrate1->richcontent->html;


echo  $itrate1->richcontent->html->body->asXML();
 print_r((string) $itrate1->richcontent->html->body->asXML());

0

Просто поставте ''. перед будь-якою змінною вона перетвориться на рядок.

$ foo = array (''. $ xml-> channel-> item-> title);


-1

Нижче наведена рекурсивна функція, яка вводить усі однодочірні елементи до String:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION - CLEAN SIMPLE XML OBJECT
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function cleanSimpleXML($xmlObject = ''){

    // LOOP CHILDREN
    foreach ($xmlObject->children() as $child) {

        // IF CONTAINS MULTIPLE CHILDREN
        if(count($child->children()) > 1 ){

            // RECURSE
            $child = cleanSimpleXML($child);

        }else{

            // CAST
            $child = (string)$child;

        }

    }

    // RETURN CLEAN OBJECT
    return $xmlObject;

} // END FUNCTION
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.