三行 xml2array
<?php
$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
?>
就是这样!
三行 xml2array
<?php
$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
?>
就是这样!
在 $_SESSION 中存储 SimpleXMLElement 值不起作用。将结果保存为对象或对象的单个元素会导致可怕的“警告:session_start() [function.session-start]:节点不再存在”错误。
例如,这不起作用
$xml = new SimpleXMLElement($page);
$country = $xml->Response->Placemark->AddressDetails->Country->CountryNameCode;
$_SESSION['country'] = $country;
这将起作用
$_SESSION['country'] = (string) $country;
这是一个递归函数,它将把给定的 SimpleXMLElement 对象转换为数组,并保留命名空间和属性。
<?php
function xmlObjToArr($obj) {
$namespace = $obj->getDocNamespaces(true);
$namespace[NULL] = NULL;
$children = array();
$attributes = array();
$name = strtolower((string)$obj->getName());
$text = trim((string)$obj);
if( strlen($text) <= 0 ) {
$text = NULL;
}
// 获取所有命名空间的信息
if(is_object($obj)) {
foreach( $namespace as $ns=>$nsUrl ) {
// 属性
$objAttributes = $obj->attributes($ns, true);
foreach( $objAttributes as $attributeName => $attributeValue ) {
$attribName = strtolower(trim((string)$attributeName));
$attribVal = trim((string)$attributeValue);
if (!empty($ns)) {
$attribName = $ns . ':' . $attribName;
}
$attributes[$attribName] = $attribVal;
}
// 子节点
$objChildren = $obj->children($ns, true);
foreach( $objChildren as $childName=>$child ) {
$childName = strtolower((string)$childName);
if( !empty($ns) ) {
$childName = $ns.':'.$childName;
}
$children[$childName][] = xmlObjToArr($child);
}
}
}
return array(
'name'=>$name,
'text'=>$text,
'attributes'=>$attributes,
'children'=>$children
);
}
?>
在使用 simple xml 并从 xml 对象获取双精度或浮点数整数时,由于 simple xml 将所有内容都返回为对象,因此在进行数学运算(+ * - /)时会出现一些错误。
例如;
<?php
$name = "somestring";
$size = 11.45;
$xml = '
<xml>
<name>somestring</name>
<size>11.45</size>
</xml>';
$xmlget = simplexml_load_string($xml)
echo $xml->size*2; // 20 结果错误
// ($xml->size 是一个对象 (int)11 和 (45) )
// 这个是正确的
echo $size*2; // 22.90
echo (float)$size*2; // 22.90
?>
如果你尝试使用此方法加载 XML 文件,但由于某些原因 CDATA 部分未加载,则应按以下方式操作
$xml = simplexml_load_file($this->filename, 'SimpleXMLElement', LIBXML_NOCDATA);
这会将 CDATA 转换为返回对象中的字符串。
补充其他人的说法,你不能直接将 $_GET 或 $_POST 值放入变量,然后使用 SimpleXML 放入属性中。你必须先将其转换为整数。
这将不起作用
<?php
$page_id = $_GET['id'];
echo $xml->page[$page_id]
?>
你会得到类似以下的信息
Notice: Trying to get property of non-object in /Applications/MAMP/htdocs/mysite/index.php on line 10
但是,这将起作用,并且比使用 (string) 或其他方法简单得多。
<?php
$page_id = intval($_GET['id']);
echo $xml->page[$page_id]
?>
简单即简单。如果你知道结构,并且只想获取标签的值
<?php
$xml = simplexml_load_file($xmlfile);
print $xml->City->Street->Address->HouseColor;
?>
警告,数字可能以字符串形式输出,空元素(如 <HouseColor></HouseColor>)会输出为数组(0)
以下是两个使用 SimpleXML 检测 feed xml 是 RSS 还是 ATOM 的快速简便函数
<?php
function is_rss($feedxml) {
@$feed = new SimpleXMLElement($feedxml);
if ($feed->channel->item) {
return true;
} else {
return false;
}
}
function is_atom($feedxml) {
@$feed = new SimpleXMLElement($feedxml);
if ($feed->entry) {
return true;
} else {
return false;
}
}
?>
这些函数接收完整的文本 feed(例如,通过 cURL 获取),并根据结果返回 true 或 false。
用于简单 SAX 读取大型 xml 的包装器 XMLReader 类
https://github.com/dkrnl/SimpleXMLReader
使用示例:http://github.com/dkrnl/SimpleXMLReader/blob/master/examples/example1.php
<?php
/**
* 简易 XML 阅读器
*
* @license 公共领域
* @author Dmitry Pyatkov(aka dkrnl) <[email protected]>
* @url http://github.com/dkrnl/SimpleXMLReader
*/
class SimpleXMLReader extends XMLReader
{
/**
* 回调函数
*
* @var array
*/
protected $callback = array();
/**
* 添加节点回调函数
*
* @param string $name
* @param callback $callback
* @param integer $nodeType
* @return SimpleXMLReader
*/
public function registerCallback($name, $callback, $nodeType = XMLREADER::ELEMENT)
{
if (isset($this->callback[$nodeType][$name])) {
throw new Exception("回调函数 $name($nodeType) 已存在.");
}
if (!is_callable($callback)) {
throw new Exception("解析器回调函数 $name($nodeType) 已存在.");
}
$this->callback[$nodeType][$name] = $callback;
return $this;
}
/**
* 移除节点回调函数
*
* @param string $name
* @param integer $nodeType
* @return SimpleXMLReader
*/
public function unRegisterCallback($name, $nodeType = XMLREADER::ELEMENT)
{
if (!isset($this->callback[$nodeType][$name])) {
throw new Exception("未知的解析器回调函数 $name($nodeType).");
}
unset($this->callback[$nodeType][$name]);
return $this;
}
/**
* 运行解析器
*
* @return void
*/
public function parse()
{
if (empty($this->callback)) {
throw new Exception("解析器回调函数为空.");
}
$continue = true;
while ($continue && $this->read()) {
if (isset($this->callback[$this->nodeType][$this->name])) {
$continue = call_user_func($this->callback[$this->nodeType][$this->name], $this);
}
}
}
/**
* 在当前节点上运行 XPath 查询
*
* @param string $path
* @param string $version
* @param string $encoding
* @return array(SimpleXMLElement)
*/
public function expandXpath($path, $version = "1.0", $encoding = "UTF-8")
{
return $this->expandSimpleXml($version, $encoding)->xpath($path);
}
/**
* 将当前节点扩展为字符串
*
* @param string $version
* @param string $encoding
* @return SimpleXMLElement
*/
public function expandString($version = "1.0", $encoding = "UTF-8")
{
return $this->expandSimpleXml($version, $encoding)->asXML();
}
/**
* 将当前节点扩展为 SimpleXMLElement
*
* @param string $version
* @param string $encoding
* @param string $className
* @return SimpleXMLElement
*/
public function expandSimpleXml($version = "1.0", $encoding = "UTF-8", $className = null)
{
$element = $this->expand();
$document = new DomDocument($version, $encoding);
$node = $document->importNode($element, true);
$document->appendChild($node);
return simplexml_import_dom($node, $className);
}
/**
* 将当前节点扩展为 DomDocument
*
* @param string $version
* @param string $encoding
* @return DomDocument
*/
public function expandDomDocument($version = "1.0", $encoding = "UTF-8")
{
$element = $this->expand();
$document = new DomDocument($version, $encoding);
$node = $document->importNode($element, true);
$document->appendChild($node);
return $document;
}
}
?>
XML 和 PHP 数组之间最大的区别在于,在 XML 文件中,即使是同级元素,元素的名称也可以相同,例如“<pa><ch /><ch /><ch /></pa>”;而在 PHP 数组中,键必须不同。
我认为 svdmeer 开发的数组结构适用于 XML,并且非常适合。
这是一个从 XML 文件转换而来的数组示例
array(
"@tag"=>"name",
"@attr"=>array(
"id"=>"1","class"=>"2")
"@text"=>"some text",
)
或者如果它有子元素,则可以是
array(
"@tag"=>"name",
"@attr"=>array(
"id"=>"1","class"=>"2")
"@items"=>array(
0=>array(
"@tag"=>"name","@text"=>"some text"
)
)
此外,我还编写了一个可以将该数组转换回 XML 的函数。
<?php
function array2XML($arr,$root) {
$xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\" ?><{$root}></{$root}>");
$f = create_function('$f,$c,$a','
foreach($a as $v) {
if(isset($v["@text"])) {
$ch = $c->addChild($v["@tag"],$v["@text"]);
} else {
$ch = $c->addChild($v["@tag"]);
if(isset($v["@items"])) {
$f($f,$ch,$v["@items"]);
}
}
if(isset($v["@attr"])) {
foreach($v["@attr"] as $attr => $val) {
$ch->addAttribute($attr,$val);
}
}
}');
$f($f,$xml,$arr);
return $xml->asXML();
}
?>
以下是一种快速将 SimpleXML 中的 nodeValue 导出到数组中的方法,使用每个 nodeValue 的路径作为键。这些路径与例如 DOMXPath 兼容。当需要在外部更新值(即在不知道底层 XML 的代码中)时,我会使用此方法。然后,我使用 DOMXPath 查找包含原始值的节点并更新它。
<?php
函数 XMLToArrayFlat($xml, &$return, $path='', $root=false)
{
$children = array();
if ($xml instanceof SimpleXMLElement) {
$children = $xml->children();
if ($root){ // 我们处于根节点
$path .= '/'.$xml->getName();
}
}
if ( count($children) == 0 ){
$return[$path] = (string)$xml;
return;
}
$seen=array();
foreach ($children as $child => $value) {
$childname = ($child instanceof SimpleXMLElement)?$child->getName():$child;
if ( !isset($seen[$childname])){
$seen[$childname]=0;
}
$seen[$childname]++;
XMLToArrayFlat($value, $return, $path.'/'.$child.'['.$seen[$childname].']');
}
}
?>
使用方法
<?php
$xml = simplexml_load_string(...一些xml字符串...);
$xmlarray = array(); // 用于保存扁平化数据
XMLToArrayFlat($xml, $xmlarray, '', true);
?>
您也可以将多个文件拉入一个数组
<?php
foreach($files as $file){
$xml = simplexml_load_file($file);
XMLToArrayFlat($xml, $xmlarray, $file.':', true);
}
?>
因此,每个键都以相应的文件名/路径为前缀。
这是一个我想到的将关联数组转换为XML的函数。也适用于多维数组。
<?php
函数 assocArrayToXML($root_element_name,$ar)
{
$xml = new SimpleXMLElement("<?xml version=\"1.0\"?><{$root_element_name}></{$root_element_name}>");
$f = create_function('$f,$c,$a','
foreach($a as $k=>$v) {
if(is_array($v)) {
$ch=$c->addChild($k);
$f($f,$ch,$v);
} else {
$c->addChild($k,$v);
}
}');
$f($f,$xml,$ar);
return $xml->asXML();
}
?>
使用xml在php中进行动态sql
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<sql>
<statement>
SELECT * FROM USERS
<call criteria="byId">WHERE id = %d</call>
<call criteria="byUsername">WHERE username = "%s"</call>;
</statement>
</sql>
index.php
<?php
函数 callMe($param) {
$search = array('byUsername' => 'dynsql');
if (isset($search[$param[1]])) {
return sprintf($param[2], $search[$param[1]]);
}
return "";
}
$xml = simplexml_load_file("test.xml");
$string = $xml->statement->asXML();
$string = preg_replace_callback('/<call criteria="(\w+)">(.*?)<\/call>/', 'callMe', $string);
$node = simplexml_load_string($string);
echo $node;
?>
显然,这个例子可以改进[在您自己的代码中]。
我在使用simplexml读取xml文件中的节点时遇到了问题。它总是返回一个SimpleXML对象,而不是节点内的文本。
示例
<?xml version="1.0" encoding="UTF-8"?>
<Test>
<Id>123</Id>
</Test>
将此xml读入名为$xml的变量,然后执行以下操作
<?php
$myId = $xml->Id;
?>
没有在$myId中返回123,而是得到了一个SimpleXMLElement对象。
解决方案很简单,当你知道了它。使用显式字符串转换。
<?php
$myId = (string)$xml->Id;
?>
两行代码将xml转换为数组
<?php
$xml = simplexml_load_string($xmlstring);
$array = (array) $xml;
?>