Как преобразовать xml документ в массив "имя тэга" => "содержание"?

poiuyt1234

Новичок
Как преобразовать xml документ в массив "имя тэга" => "содержание"?

Вот документ:
<?xml version='1.0' encoding='UTF-8'?>
<rsp stat='ok'>
<profile>
<displayName>
brian
</displayName>
<identifier>
654654654654
</identifier>
<preferredUsername>
brian
</preferredUsername>
<providerName>
Other
</providerName>
<url>
google.com
</url>
</profile>
</rsp>

Сначала я его загоняю в объект domdocument с помощью loadXML().

А как domdocument преобразовать в ассоциативный текстовый маcсив "имя тэга" => "значение" (например "identifier" => "654654654654")?
 

poiuyt1234

Новичок
Эт я все читал.. но никак не могу понять как выбрать имена тегов..
 

poiuyt1234

Новичок
Попытался использовать get_elements_by_tagname() а тут ошибка:
Fatal error: Call to undefined method DOMDocument::get_elements_by_tagname()
 

Beavis

Banned
poiuyt1234
разве по той ссылке, что я тебе дал, упоминалась такая функция?
ты вообще с какой версией php работаешь?)
 

poiuyt1234

Новичок
самой последней.

вот эта функция: getElementsByTagName() возвращает пустое значение почему-то..
 

Beavis

Banned
у тебя PHP6 стоит?

ты уж определись get_elements_by_tagname() или getElementsByTagName()
в мануале есть примеры как правильно пользоваться этой функцией
 

poiuyt1234

Новичок
$t = $result -> saveXML();
echo ("$t");
Выводится вот это:
<?xml version='1.0' encoding='UTF-8'?>
<rsp stat='ok'>
<profile>
<displayName>
brian
</displayName>
<identifier>
654654654654
</identifier>
<preferredUsername>
brian
</preferredUsername>
<providerName>
Other
</providerName>
<url>
google.com
</url>
</profile>
</rsp>

А вот этот код:
$q = $result -> getElementsByTagName("identifier");
$y = ($q->textcontent);
print_r($y);

или

$q = $result -> getElementsByTagName("identifier");
$y = ($q->nodevalue);
print_r($y);

Не выводит ничего вообще..

-~{}~ 15.02.09 14:26:

использую php5
 

Beavis

Banned
1. Посмотри внимательно что возвращает метод getElementsByTagName и что от него ожидаешь ты.

2. $q->nodevalue и $q->nodeValue не одно и то же!

3. Вместо print_r пользуйся var_dump
 

poiuyt1234

Новичок
я хочу выбрать элемент с определенным именем тэга и вывести его значение..
 

Beavis

Banned
Если хочешь научиться - информации достаточно. Если хочешь чтоб за тебя это задание сделали другие - так и скажи.
 

CHEM_Eugene

Новичок
Когда юзаешь getElementsByTagName() всегда получаешь массив (или список), поэтому $q->nodevalue бессмысленно, надо обращаться к нулевому элементу в этом списке. Код писать лень, подсказку я дал.
 

Beavis

Banned
poiuyt1234
кстати, с помощью SimpleXML задача решается в одну-две строчки...
 

pilot911

Новичок
пользуйся этой функцией, в которую передаешь xml вида

PHP:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<CMFlocallang>
	<meta type="array">
		<description>Web module.</description>
		<type>widget html</type>
	</meta>
	<data type="array">
		<label index="ext.title">GALLERY PHOTO LIST</label>
		<label index="_category_id">Category ID</label>
		<label index="_limit">Limit</label>
		<label index="_category">Category</label>
   	</data>
</CMFlocallang>

и получаешь многомерный массив

PHP:
	/**
	 * Converts an XML string to a PHP array.
	 * This is the reverse function of array2xml()
	 *
	 * @param	string		XML content to convert into an array
	 * @param	string		The tag-prefix resolve, eg. a namespace like "T3:"
	 * @param	boolean		If set, the document tag will be set in the key "_DOCUMENT_TAG" of the output array
	 * @return	mixed		If the parsing had errors, a string with the error message is returned. Otherwise an array with the content.
	 * @see array2xml()
	 */
	static	function xml2array($string,$NSprefix='',$reportDocTag=false) {
 
			// Create parser:
		$parser = xml_parser_create();
		$vals = array();
		$index = array();

		xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
		xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);

			// PHP5 fix of charset awareness:
			// Problem is: PHP5 apparently detects the charset of the XML file (or defaults to utf-8) and will AUTOMATICALLY convert the content to either utf-8, iso-8859-1 or us-ascii. PHP4 just passed the content through without taking action regarding the charset.
			// In TYPO3 we expect that the charset of XML content is NOT handled in the parser but internally in TYPO3 instead. Therefore it would be very nice if PHP5 could be configured to NOT process the charset of the files. But this is not possible for now.
			// What we do here fixes the problem but ONLY if the charset is utf-8, iso-8859-1 or us-ascii. That should work for most TYPO3 installations, in particular if people use utf-8 which we highly recommend.
		if ((double)phpversion()>=5)	{
			$ereg_result = array();
			ereg('^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"',mb_substr($string,0,200),$ereg_result);
			$theCharset = 'utf-8';
			xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);  // us-ascii / utf-8 / iso-8859-1
		}

			// Parse content:
		xml_parse_into_struct($parser, $string, $vals, $index);

			// If error, return error message:
		if (xml_get_error_code($parser))	{
			return 'Line '.xml_get_current_line_number($parser).': '.xml_error_string(xml_get_error_code($parser));
		}
		xml_parser_free($parser);

			// Init vars:
		$stack = array(array());
		$stacktop = 0;
		$current=array();
		$tagName = '';
		$documentTag = '';

			// Traverse the parsed XML structure:
		foreach($vals as $key => $val) {

				// First, process the tag-name (which is used in both cases, whether "complete" or "close")
			$tagName = $val['tag'];
			if (!$documentTag)	$documentTag = $tagName;

				// Test for name space:
			$tagName = ($NSprefix && mb_substr($tagName,0,strlen($NSprefix))==$NSprefix) ? mb_substr($tagName,strlen($NSprefix)) : $tagName;

				// Test for numeric tag, encoded on the form "nXXX":
			$testNtag = mb_substr($tagName,1);	// Closing tag.
			$tagName = (mb_substr($tagName,0,1)=='n' && !strcmp(intval($testNtag),$testNtag)) ? intval($testNtag) : $tagName;

				// Test for alternative index value:
			if (isset($val['attributes']) && isset($val['attributes']['index']) && strlen($val['attributes']['index']))	{ $tagName = $val['attributes']['index']; }

				// Setting tag-values, manage stack:
			switch($val['type'])	{
				case 'open':		// If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
					$current[$tagName] = array();	// Setting blank place holder
					$stack[$stacktop++] = $current;
					$current = array();
				break;
				case 'close':	// If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
					$oldCurrent = $current;
					$current = $stack[--$stacktop];
					end($current);	// Going to the end of array to get placeholder key, key($current), and fill in array next:
					$current[key($current)] = $oldCurrent;
					unset($oldCurrent);
				break;
				case 'complete':	// If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
					if (isset($val['attributes']) && isset($val['attributes']['base64']) &&  $val['attributes']['base64'])	{
						$current[$tagName] = base64_decode($val['value']);
					} else {
						$current[$tagName] = (string)(isset($val['value']) ? $val['value'] : ''); // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!!
						if (isset($val['attributes']) && isset($val['attributes']['type']))	{
								// Cast type:
							switch((string)$val['attributes']['type'])	{
								case 'integer':
									$current[$tagName] = (integer)$current[$tagName];
								break;
								case 'double':
									$current[$tagName] = (double)$current[$tagName];
								break;
								case 'boolean':
									$current[$tagName] = (bool)$current[$tagName];
								break;
								case 'array':
									$current[$tagName] = array();	// MUST be an empty array since it is processed as a value; Empty arrays would end up here because they would have no tags inside...
								break;
							}
						}
					}
				break;
			}
		}

		if ($reportDocTag)	{
			$current[$tagName]['_DOCUMENT_TAG'] = $documentTag;
		}

			// Finally return the content of the document tag.
		return $current[$tagName];
	}
 

cDLEON

Онанист РНРСlub
pilot911
Так сильно хотелось свой мегакрутой код показать? )))
 

poiuyt1234

Новичок
Я ничего не понимаю...

Написал код:
$xpath = new DOMXPath($result);
$nodes = $xpath->query("/rsp/profile");
$identifiers = array();
For ($i=0; $i<$nodes->length; $i++)
{ $b = $nodes -> item($i);
$g = $b -> nodeName;
$h = $b -> nodeValue;
$identifiers[$g] = $h;
};
foreach ($identifiers as $k => $v) {
echo "<b>$k</b> => <tt> $v </tt> <br>\n";
}
Вывел: profile => brian654654654654brianOthergoogle.com

Почему так??


Написал другой код:

$q = $result -> getElementsByTagName("profile");
$nodes = $q -> childNodes();
$identifiers = array();
For ($i=0; $i<$nodes->length; $i++)
{ $b = $nodes -> item($i);
$g = $b -> nodeName;
$h = $b -> nodeValue;
$identifiers[$g] = $h;
};
foreach ($identifiers as $k => $v) {
echo "<b>$k</b> => <tt> $v </tt> <br>\n";
}


Не вывел ничего вообще.. что, это:
<displayName>
brian
</displayName>
<identifier>
654654654654
</identifier>
<preferredUsername>
brian
</preferredUsername>
<providerName>
Other
</providerName>
<url>
google.com
</url>
не childnodes для profile??
 

Beavis

Banned
poiuyt1234
рано тебе ещё с DOM возиться =)
смотри как с SimpleXML всё просто:
PHP:
$sxml = new SimpleXMLElement($xml);
foreach ($sxml->profile as $profile) $data[] = array_map("trim", (array)$profile);
и всё!

-~{}~ 16.02.09 23:57:

вместо
Автор оригинала: poiuyt1234
$g = $b -> nodeName;
$h = $b -> nodeValue;
$identifiers[$g] = $h;
надо
PHP:
$child = $b->firstChild;
$identifiers[$i] = array();
do {
	if ($child->nodeType == XML_ELEMENT_NODE) $identifiers[$i][$child->nodeName] = trim($child->nodeValue);
} while ($child = $child->nextSibling);
 
Сверху