将 PHP 关联数组传入和传出 XML
Posted
技术标签:
【中文标题】将 PHP 关联数组传入和传出 XML【英文标题】:Passing PHP associative arrays to and from XML 【发布时间】:2010-09-11 02:11:33 【问题描述】:有没有一种简单的方法可以将 php 关联数组与 XML 进行编组?例如,我有以下数组:
$items = array("1", "2",
array(
"item3.1" => "3.1",
"item3.2" => "3.2"
"isawesome" => true
)
);
如何以尽可能少的行将其转换为类似于以下 XML 的内容,然后再返回?
<items>
<item>1</item>
<item>2</item>
<item>
<item3_1>3.1</item3_1>
<item3_2>3.2</item3_2>
<isawesome>true</isawesome>
</item>
</items>
我真的不在乎是否必须稍微更改数组结构,或者输出的 XML 是否与上面的示例不同。我一直在尝试使用 PHP 的 XMLReader 和 XMLWriter,但是文档太差了,因此我生成的代码看起来不像我认为的那样:
$xml = SomeXMLWriter::writeArrayToXml($items);
$array = SomeXMLWriter::writeXmlToArray($xml);
在不编写我自己的自定义类的情况下获得 PHP 数组的基本原始 XML 转储真的比这更难吗?
我尽量避免使用 PEAR。除了我在使用它时遇到的配置问题之外,我从来没有使用过我曾经使用过的任何软件包。
【问题讨论】:
【参考方案1】:SimpleXML 非常适合您使用。
【讨论】:
【参考方案2】:对于那些不使用 PEAR 包但已安装 PHP5 的人。这对我有用:
/**
* Build A XML Data Set
*
* @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
* @param string $startElement Root Opening Tag, default fx_request
* @param string $xml_version XML Version, default 1.0
* @param string $xml_encoding XML Encoding, default UTF-8
* @return string XML String containig values
* @return mixed Boolean false on failure, string XML result on success
*/
public function buildXMLData($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8')
if(!is_array($data))
$err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
trigger_error($err);
if($this->_debug) echo $err;
return false; //return false error occurred
$xml = new XmlWriter();
$xml->openMemory();
$xml->startDocument($xml_version, $xml_encoding);
$xml->startElement($startElement);
/**
* Write XML as per Associative Array
* @param object $xml XMLWriter Object
* @param array $data Associative Data Array
*/
function write(XMLWriter $xml, $data)
foreach($data as $key => $value)
if(is_array($value))
$xml->startElement($key);
write($xml, $value);
$xml->endElement();
continue;
$xml->writeElement($key, $value);
write($xml, $data);
$xml->endElement();//write end element
//Return the XML results
return $xml->outputMemory(true);
【讨论】:
如果你的数据中有非关联数组(或者更确切地说,数组键中有数字),添加一个'if (is_numeric($key)) $key = "item";'在 foreach 块的开头(在 is_array 之前)就可以了。 为了也能处理数值数组,添加$fKey = is_numeric($key) ? 'numericValue' : $key;
before if(is_array($value))
语句,并在foreach 语句的其余部分使用$fKey
。
哦@VassilisGr,我在那里做了类似的事情:if(is_numeric($key)) $key = 'node';
并将function write
移到外面,你不能声明两次相同的函数,但@Conrad 现在会这样做。 (该死,我现在看到@disq 评论哈哈)【参考方案3】:
我也遇到过一些同样的问题,所以我创建了两个类:
bXml
扩展 SimpleXml 并纠正其存在的一些问题的类。就像无法添加 CData 节点或 Comment 节点一样。我还添加了一些附加功能,例如使用 php 流功能添加子节点 $oXml->AddChild("file:///user/data.xml")
或添加 XML 字符串子节点,如 $oXml->AddChild("<more><xml>yes</xml></more>");
,但基本上我只是想修复 simpleXML 问题。
bArray
我扩展了 ArrayObject 类,以便所有数组功能都可以面向对象且一致,因此您无需记住 array_walk 通过引用对数组进行操作,而 array_filter 通过值对数组进行操作。因此,您可以执行$oArray->flip()->Reverse()->Walk(/*callback*/);
之类的操作,然后仍以您通常希望$oArray[key]
的方式访问该值。
这两种方法都将自身输出为数组和 Xml,因此您可以在它们之间无缝跳转。所以你可以$oXml->AsArray();
或$oArray->AsXml();
我发现这样做比在array2xml 或xml2array 方法之间不断地来回传递东西更容易。
http://code.google.com/p/blibrary/source
这两个类都可以被覆盖以创建您选择的自定义类,并且可以彼此独立使用。
【讨论】:
扩展 SimpleXML 来做到这一点是一个非常好的主意!【参考方案4】:class Xml
public static function from_array($arr, $xml = NULL)
$first = $xml;
if($xml === NULL) $xml = new SimpleXMLElement('<root/>');
foreach ($arr as $k => $v)
is_array($v)
? self::from_array($v, $xml->addChild($k))
: $xml->addChild($k, $v);
return ($first === NULL) ? $xml->asXML() : $xml;
public static function to_array($xml)
$xml = simplexml_load_string($xml);
$json = json_encode($xml);
return json_decode($json,TRUE);
$xml = xml::from_array($array);
$array = xml::to_array($xml);
【讨论】:
【参考方案5】:一般尝试 Zend_Config 和 Zend Framework。
我想这将是一个两步过程:数组到 Zend_Config,Zend_Config 到 XML。
【讨论】:
【参考方案6】:听起来像是 SimpleXML 的工作。
我会建议一个稍微不同的 XML 结构..
想知道为什么需要从数组转换 -> XML 并返回。如果您可以按照您所说的修改数组结构,为什么不直接生成 XML 呢?如果已经存在采用该数组配置的某些代码,只需修改它以接受 XML。然后你有1种数据格式/输入类型,根本不需要转换..
<items>
<item id="1"/>
<item id="2"/>
<item id="3">
<subitems>
<item id="3.1"/>
<item id="3.2" isawesome="true"/>
</subitems>
</item>
</items>
【讨论】:
【参考方案7】:这是我编写的一个函数,用于获取 XML 并将其转换为 PHP 关联数组。一个警告是 id 当前不处理属性或 c 数据。虽然它会通过将重复的 XML 标签放入以标签命名的数组中来处理同一级别的重复 XML 标签。
<?php
$xml_req1 = <<<XML
<?xml version="1.0"?>
<Vastera:CustomerValidation_RequestInfo
xmlns:Vastera="http://ndc-ah-prd.am.mot.com:10653/MotVastera_CustomerValidation/MC000078/Docs/">
<PartnerID>5550000100-003</PartnerID>
<PartnerType>PTNR_INTER_CONSIGNEE</PartnerType>
<OperatingUnit>100</OperatingUnit>
<Status>ACTIVE</Status>
<CustomerSeqNumber>111</CustomerSeqNumber>
<CustomerName>Greg Co</CustomerName>
<Address1>123 Any Ln</Address1>
<Address2>?</Address2>
<Address3>?</Address3>
<Address4>?</Address4>
<Address5>?</Address5>
<City>Someplace</City>
<PostalCode>603021</PostalCode>
<State>CA</State>
<CountryCode>US</CountryCode>
<TaxReference>222</TaxReference>
<PartyRelated>Y</PartyRelated>
<BusinessUnit>GSBU</BusinessUnit>
<Region>GSRGN</Region>
<LocationName>DBA Mac Head Computing</LocationName>
<LoadOnly>N</LoadOnly>
<VSTM>333</VSTM>
<MilitaryCustomerFlag>Y</MilitaryCustomerFlag>
<USFederalGovernmentCustomer>Y</USFederalGovernmentCustomer>
<Non-USGovernmentCustomer>Y</Non-USGovernmentCustomer>
<Vastera:EPCIActivity>
<EPCIActivityNuclearCode>NUCLEAR</EPCIActivityNuclearCode>
<EPCIActivityNuclearValue>N</EPCIActivityNuclearValue>
<EPCIActivityNuclearApproveDate>2011-05-16:07:19:37</EPCIActivityNuclearApproveDate>
<EPCIActivityNuclearExpireDate>2056-12-31:12:00:00</EPCIActivityNuclearExpireDate>
<EPCIActivityNuclearCountry>US</EPCIActivityNuclearCountry>
<EPCIActivityChemBioCode>CHEM_BIO</EPCIActivityChemBioCode>
<EPCIActivityChemBioValue>N</EPCIActivityChemBioValue>
<EPCIActivityChemBioApproveDate>2011-05-16:07:19:37</EPCIActivityChemBioApproveDate>
<EPCIActivityChemBioExpireDate>2056-12-31:12:00:00</EPCIActivityChemBioExpireDate>
<EPCIActivityChemBioCountry>US</EPCIActivityChemBioCountry>
<EPCIActivityMissileCode>MISSILE</EPCIActivityMissileCode>
<EPCIActivityMissileValue>N</EPCIActivityMissileValue>
<EPCIActivityMissileApproveDate>2011-05-16:07:19:37</EPCIActivityMissileApproveDate>
<EPCIActivityMissileExpireDate>2056-12-31:12:00:00</EPCIActivityMissileExpireDate>
<EPCIActivityMissileCountry>US</EPCIActivityMissileCountry>
</Vastera:EPCIActivity>
<SourceSystem>GSB2BSS</SourceSystem>
<CreatedDate>2011-05-16:07:18:55</CreatedDate>
<CreatedBy>c18530</CreatedBy>
<LastModifiedDate>2011-05-16:07:18:55</LastModifiedDate>
<LastModifiedBy>c18530</LastModifiedBy>
<ContactName>Greg, "Da Man" Skluacek</ContactName>
<ContactTitle>Head Honcho</ContactTitle>
<ContactPhone>555-555-5555</ContactPhone>
<ContactFax>666-666-6666</ContactFax>
<ContactEmail>gskluzacek@gregco.com</ContactEmail>
<ContactWeb>www.gregco.com</ContactWeb>
</Vastera:CustomerValidation_RequestInfo>
XML;
$xml_req2 = <<<XML
<?xml version="1.0"?>
<order>
<orderNumber>123</orderNumber>
<customerAddress>
<type>Ship To</type>
<name>Bob McFly</name>
<addr1>123 Lincoln St</addr1>
<city>Chicago</city>
<state>IL</state>
<zip>60001</zip>
</customerAddress>
<customerAddress>
<type>Bill To</type>
<name>McFly Products Inc.</name>
<addr1>P.O. Box 6695</addr1>
<city>New York</city>
<state>NY</state>
<zip>99081-6695</zip>
</customerAddress>
<item>
<line>1</line>
<part>123001A</part>
<qty>5</qty>
<price>10.25</price>
</item>
<item>
<line>2</line>
<part>456002B</part>
<qty>3</qty>
<price>20.50</price>
</item>
<item>
<line>3</line>
<part>789003C</part>
<qty>1</qty>
<price>41.00</price>
</item>
<orderSubTotal>133.25</orderSubTotal>
<tax>6.66</tax>
<shipping>10.00</shipping>
<orderTotal>149.91</orderTotal>
</order>
XML;
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->loadXML($xml_req1);
$arr = xml_to_arr($doc->documentElement);
print "\n\n----\n\n";
print_r($arr);
print "\n\n----\n\n";
$doc2 = new DOMDocument();
$doc2->preserveWhiteSpace = false;
$doc2->loadXML($xml_req2);
$arr2 = xml_to_arr($doc2->documentElement);
print "\n\n----\n\n";
print_r($arr2);
print "\n\n----\n\n";
exit;
function xml_to_arr($curr_node)
$val_array = array();
$typ_array = array();
foreach($curr_node->childNodes as $node)
if ($node->nodeType == XML_ELEMENT_NODE)
$val = xml_to_arr($node);
if (array_key_exists($node->tagName, $val_array))
if (!is_array($val_array[$node->tagName]) || $type_array[$node->tagName] == 'hash')
$existing_val = $val_array[$node->tagName];
unset($val_array[$node->tagName]);
$val_array[$node->tagName][0] = $existing_val;
$type_array[$node->tagName] = 'array';
$val_array[$node->tagName][] = $val;
else
$val_array[$node->tagName] = $val;
if (is_array($val))
$type_array[$node->tagName] = 'hash';
// end if array key exists
// end if elment node
// end for each
if (count($val_array) == 0)
return $curr_node->nodeValue;
else
return $val_array;
// end function xml to arr
?>
示例输出
----
Array
(
[PartnerID] => 5550000100-003
[PartnerType] => PTNR_INTER_CONSIGNEE
[OperatingUnit] => 100
[Status] => ACTIVE
[CustomerSeqNumber] => 111
[CustomerName] => Greg Co
[Address1] => 123 Any Ln
[Address2] => ?
[Address3] => ?
[Address4] => ?
[Address5] => ?
[City] => Somplace
[PostalCode] => 60123
[State] => CA
[CountryCode] => US
[TaxReference] => 222
[PartyRelated] => Y
[BusinessUnit] => GSBU
[Region] => GSRGN
[LocationName] => DBA Mac Head Computing
[LoadOnly] => N
[VSTM] => 333
[MilitaryCustomerFlag] => Y
[USFederalGovernmentCustomer] => Y
[Non-USGovernmentCustomer] => Y
[Vastera:EPCIActivity] => Array
(
[EPCIActivityNuclearCode] => NUCLEAR
[EPCIActivityNuclearValue] => N
[EPCIActivityNuclearApproveDate] => 2011-05-16:07:19:37
[EPCIActivityNuclearExpireDate] => 2056-12-31:12:00:00
[EPCIActivityNuclearCountry] => US
[EPCIActivityChemBioCode] => CHEM_BIO
[EPCIActivityChemBioValue] => N
[EPCIActivityChemBioApproveDate] => 2011-05-16:07:19:37
[EPCIActivityChemBioExpireDate] => 2056-12-31:12:00:00
[EPCIActivityChemBioCountry] => US
[EPCIActivityMissileCode] => MISSILE
[EPCIActivityMissileValue] => N
[EPCIActivityMissileApproveDate] => 2011-05-16:07:19:37
[EPCIActivityMissileExpireDate] => 2056-12-31:12:00:00
[EPCIActivityMissileCountry] => US
)
[SourceSystem] => GSB2BSS
[CreatedDate] => 2011-05-16:07:18:55
[CreatedBy] => c18530
[LastModifiedDate] => 2011-05-16:07:18:55
[LastModifiedBy] => c18530
[ContactName] => Greg, "Da Man" Skluacek
[ContactTitle] => Head Honcho
[ContactPhone] => 555-555-5555
[ContactFax] => 666-666-6666
[ContactEmail] => gskluzacek@gregco.com
[ContactWeb] => www.gregco.com
)
----
Array
(
[orderNumber] => 123
[customerAddress] => Array
(
[0] => Array
(
[type] => Ship To
[name] => Bob McFly
[addr1] => 123 Lincoln St
[city] => Chicago
[state] => IL
[zip] => 60001
)
[1] => Array
(
[type] => Bill To
[name] => McFly Products Inc.
[addr1] => P.O. Box 6695
[city] => New York
[state] => NY
[zip] => 99081-6695
)
)
[item] => Array
(
[0] => Array
(
[line] => 1
[part] => 123001A
[qty] => 5
[price] => 10.25
)
[1] => Array
(
[line] => 2
[part] => 456002B
[qty] => 3
[price] => 20.50
)
[2] => Array
(
[line] => 3
[part] => 789003C
[qty] => 1
[price] => 41.00
)
)
[orderSubTotal] => 133.25
[tax] => 6.66
[shipping] => 10.00
[orderTotal] => 149.91
)
--------
【讨论】:
【参考方案8】:嘿@Conrad,我只是修改了您的代码,以便与数字数组一起工作:
/**
* Build A XML Data Set
*
* @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
* @param string $startElement Root Opening Tag, default fx_request
* @param string $xml_version XML Version, default 1.0
* @param string $xml_encoding XML Encoding, default UTF-8
* @return string XML String containig values
* @return mixed Boolean false on failure, string XML result on success
*/
public static function arrayToXML($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8')
if(!is_array($data))
$err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
trigger_error($err);
if($this->_debug) echo $err;
return false; //return false error occurred
$xml = new XmlWriter();
$xml->openMemory();
$xml->startDocument($xml_version, $xml_encoding);
$xml->startElement($startElement);
/**
* Write XML as per Associative Array
* @param object $xml XMLWriter Object
* @param array $data Associative Data Array
*/
function write(XMLWriter $xml, $data)
foreach($data as $key => $value)
if (is_array($value) && isset($value[0]))
foreach($value as $itemValue)
//$xml->writeElement($key, $itemValue);
if(is_array($itemValue))
$xml->startElement($key);
write($xml, $itemValue);
$xml->endElement();
continue;
if (!is_array($itemValue))
$xml->writeElement($key, $itemValue."");
else if(is_array($value))
$xml->startElement($key);
write($xml, $value);
$xml->endElement();
continue;
if (!is_array($value))
$xml->writeElement($key, $value."");
write($xml, $data);
$xml->endElement();//write end element
//returns the XML results
return $xml->outputMemory(true);
所以你可以转换这个:
$mArray["invitations"]["user"][0]["name"] = "paco";
$mArray["invitations"]["user"][0]["amigos"][0] = 82;
$mArray["invitations"]["user"][0]["amigos"][1] = 29;
$mArray["invitations"]["user"][0]["amigos"][2] = 6;
$mArray["invitations"]["user"][1]["name"] = "jose";
$mArray["invitations"]["user"][1]["amigos"][0] = 43;
$mArray["invitations"]["user"][1]["amigos"][1]["tuyos"] = 32;
$mArray["invitations"]["user"][1]["amigos"][1]["mios"] = 79;
$mArray["invitations"]["user"][1]["amigos"][2] = 11;
$mArray["invitations"]["user"][2]["name"] = "luis";
$mArray["invitations"]["user"][2]["amigos"][0] = 65;
进入这个xml:
<invitations>
<user>
<name>paco</name>
<amigos>82</amigos>
<amigos>29</amigos>
<amigos>6</amigos>
</user>
<user>
<name>jose</name>
<amigos>43</amigos>
<amigos>
<tuyos>32</tuyos>
<mios>79</mios>
</amigos>
<amigos>11</amigos>
</user>
<user>
<name>luis</name>
<amigos>65</amigos>
</user>
我希望我能帮助别人解决这个问题
【讨论】:
【参考方案9】:你见过 PEAR 包 XML_Serializer 吗?
pear_php_XML_Serializer
【讨论】:
【参考方案10】:我同意这是 PHP 文档已经放弃的一个领域,但对我来说,我总是将 SimpleXML 与 xml2Array 函数之类的东西混合使用。借助 print_r 之类的转储函数,您从 simpleXML 获得的 Xml 并不难导航。
【讨论】:
【参考方案11】:这建立在 Ángel López 的回答之上。添加了对属性的支持。如果元素有属性,则以@为前缀,并以空字符串为键引用实际元素内容。
/**
* Build an XML Data Set
*
* @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
* @param string $startElement Root Opening Tag, default fx_request
* @param string $xml_version XML Version, default 1.0
* @param string $xml_encoding XML Encoding, default UTF-8
* @return string XML String containig values
* @return mixed Boolean false on failure, string XML result on success
*/
function arrayToXML($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8')
if(!is_array($data))
$err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
trigger_error($err);
//if($this->_debug) echo $err;
return false; //return false error occurred
$xml = new XmlWriter();
$xml->openMemory();
$xml->startDocument($xml_version, $xml_encoding);
$xml->startElement($startElement);
/**
* Write keys in $data prefixed with @ as XML attributes, if $data is an array. When an @ prefixed key is found, a '' key is expected to indicate the element itself.
* @param object $xml XMLWriter Object
* @param array $data with attributes filtered out
*/
function writeAttr(XMLWriter $xml, $data)
if(is_array($data))
$nonAttributes = array();
foreach($data as $key => $val)
//handle an attribute with elements
if($key[0] == '@')
$xml->writeAttribute(substr($key, 1), $val);
else if($key == '')
if(is_array($val)) $nonAttributes = $val;
else $xml->text("$val");
//ignore normal elements
else $nonAttributes[$key] = $val;
return $nonAttributes;
else return $data;
/**
* Write XML as per Associative Array
* @param object $xml XMLWriter Object
* @param array $data Associative Data Array
*/
function writeEl(XMLWriter $xml, $data)
foreach($data as $key => $value)
if(is_array($value) && isset($value[0])) //numeric array
foreach($value as $itemValue)
if(is_array($itemValue))
$xml->startElement($key);
$itemValue = writeAttr($xml, $itemValue);
writeEl($xml, $itemValue);
$xml->endElement();
else
$itemValue = writeAttr($xml, $itemValue);
$xml->writeElement($key, "$itemValue");
else if(is_array($value)) //associative array
$xml->startElement($key);
$value = writeAttr($xml, $value);
writeEl($xml, $value);
$xml->endElement();
else //scalar
$value = writeAttr($xml, $value);
$xml->writeElement($key, "$value");
writeEl($xml, $data);
$xml->endElement();//write end element
//returns the XML results
return $xml->outputMemory(true);
所以你可以转换这个:
$mArray["invitations"]["user"][0]["@name"] = "paco";
$mArray["invitations"]["user"][0][""]["amigos"][0] = 82;
$mArray["invitations"]["user"][0][""]["amigos"][1] = 29;
$mArray["invitations"]["user"][0][""]["amigos"][2] = 6;
$mArray["invitations"]["user"][1]["@name"] = "jose";
$mArray["invitations"]["user"][1][""]["amigos"][0] = 43;
$mArray["invitations"]["user"][1][""]["amigos"][1]["tuyos"] = 32;
$mArray["invitations"]["user"][1][""]["amigos"][1]["mios"] = 79;
$mArray["invitations"]["user"][1][""]["amigos"][2] = 11;
$mArray["invitations"]["user"][2]["@name"] = "luis";
$mArray["invitations"]["user"][2][""]["amigos"][0] = 65;
进入这个xml:
<invitations>
<user name="paco">
<amigos>82</amigos>
<amigos>29</amigos>
<amigos>6</amigos>
</user>
<user name="jose">
<amigos>43</amigos>
<amigos>
<tuyos>32</tuyos>
<mios>79</mios>
</amigos>
<amigos>11</amigos>
</user>
<user name="luis">
<amigos>65</amigos>
</user>
</invitations>
谢谢天使。
【讨论】:
很酷,但如果你像这样制作 assoc 数组,它就不起作用了:array('123' => 'asdf')
也许你应该检查每个键是否是数字。【参考方案12】:
根据这里的答案,我制作了 github repo https://github.com/jmarceli/array2xml
也许不是互联网上最漂亮的 repo,但代码似乎运行良好。
这里是可以使用的代码:
// Based on: http://***.com/questions/99350/passing-php-associative-arrays-to-and-from-xml
class ArrayToXML
private $version;
private $encoding;
/*
* Construct ArrayToXML object with selected version and encoding
*
* for available values check XmlWriter docs http://www.php.net/manual/en/function.xmlwriter-start-document.php
* @param string $xml_version XML Version, default 1.0
* @param string $xml_encoding XML Encoding, default UTF-8
*/
public function __construct($xmlVersion = '1.0', $xmlEncoding = 'UTF-8')
$this->version = $xmlVersion;
$this->encoding = $xmlEncoding;
/**
* Build an XML Data Set
*
* @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
* @param string $startElement Root Opening Tag, default data
* @return string XML String containig values
* @return mixed Boolean false on failure, string XML result on success
*/
public function buildXML($data, $startElement = 'data')
if(!is_array($data))
$err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class: ".__CLASS__." Method: ".__METHOD__;
trigger_error($err);
//if($this->_debug) echo $err;
return false; //return false error occurred
$xml = new XmlWriter();
$xml->openMemory();
$xml->startDocument($this->version, $this->encoding);
$xml->startElement($startElement);
$this->writeEl($xml, $data);
$xml->endElement();//write end element
//returns the XML results
return $xml->outputMemory(true);
/**
* Write keys in $data prefixed with @ as XML attributes, if $data is an array.
* When an @ prefixed key is found, a '%' key is expected to indicate the element itself,
* and '#' prefixed key indicates CDATA content
*
* @param object $xml XMLWriter Object
* @param array $data with attributes filtered out
*/
protected function writeAttr(XMLWriter $xml, $data)
if(is_array($data))
$nonAttributes = array();
foreach($data as $key => $val)
//handle an attribute with elements
if($key[0] == '@')
$xml->writeAttribute(substr($key, 1), $val);
else if($key[0] == '%')
if(is_array($val)) $nonAttributes = $val;
else $xml->text($val);
elseif($key[0] == '#')
if(is_array($val)) $nonAttributes = $val;
else
$xml->startElement(substr($key, 1));
$xml->writeCData($val);
$xml->endElement();
//ignore normal elements
else $nonAttributes[$key] = $val;
return $nonAttributes;
else return $data;
/**
* Write XML as per Associative Array
*
* @param object $xml XMLWriter Object
* @param array $data Associative Data Array
*/
protected function writeEl(XMLWriter $xml, $data)
foreach($data as $key => $value)
if(is_array($value) && !$this->isAssoc($value)) //numeric array
foreach($value as $itemValue)
if(is_array($itemValue))
$xml->startElement($key);
$itemValue = $this->writeAttr($xml, $itemValue);
$this->writeEl($xml, $itemValue);
$xml->endElement();
else
$itemValue = $this->writeAttr($xml, $itemValue);
$xml->writeElement($key, "$itemValue");
else if(is_array($value)) //associative array
$xml->startElement($key);
$value = $this->writeAttr($xml, $value);
$this->writeEl($xml, $value);
$xml->endElement();
else //scalar
$value = $this->writeAttr($xml, $value);
$xml->writeElement($key, "$value");
/*
* Check if array is associative with string based keys
* FROM: http://***.com/questions/173400/php-arrays-a-good-way-to-check-if-an-array-is-associative-or-sequential/4254008#4254008
*
* @param array $array Array to check
*/
protected function isAssoc($array)
return (bool)count(array_filter(array_keys($array), 'is_string'));
之后,只需使用 ArrayToXML
类。示例:
$xml = new ArrayToXML();
print $xml->buildXML($input);
【讨论】:
【参考方案13】:下面的类使用simplexml实现相同,只需要遍历数组并调用ximplexml的addchild即可。
http://snipplr.com/view.php?codeview&id=3491
【讨论】:
【参考方案14】:从xml字符串中获取assoc数组的最简单方法:
<?
$data_array = (array) simplexml_load_string($xml_string);
?>
【讨论】:
【参考方案15】:/**
* Write XML as per Associative Array
* @param object $xml XMLWriter Object
* @param array $data Associative Data Array
*/
function writeXmlRecursive(XMLWriter $xml, $data)
foreach($data as $key => $value)
if (is_array($value) && isset($value[0]))
$xml->startElement($key);
foreach($value as $itemValue)
if(is_array($itemValue))
writeXmlRecursive($xml, $itemValue);
else
$xml->writeElement($key, $itemValue."");
$xml->endElement();
else if(is_array($value))
$xml->startElement($key);
writeXmlRecursive($xml, $value);
$xml->endElement();
continue;
if (!is_array($value))
$xml->writeElement($key, $value."");
这是最终版本,它可以从具有 4 个嵌套级别的数组中提供我想要的 ahat
<items>
<item>
<id_site>59332</id_site>
<id>33</id>
<code>196429985</code>
<tombid>23</tombid>
<tombcode>196429985</tombcode>
<religion></religion>
<lastname>lastname</lastname>
<firstname>name</firstname>
<patronymicname>patronymicname</patronymicname>
<sex>1</sex>
<birthday>2</birthday>
<birthmonth>4</birthmonth>
<birthyear>1946</birthyear>
<deathday>13</deathday>
<deathmonth>5</deathmonth>
<deathyear>2006</deathyear>
<s_comments></s_comments>
<graveyard>17446</graveyard>
<latitude></latitude>
<longitude></longitude>
<images>
<image>
<siteId>52225</siteId>
<fileId>62</fileId>
<prefix>0</prefix>
<path>path</path>
</image>
<image>
<siteId>52226</siteId>
<fileId>63</fileId>
<prefix>0</prefix>
<path>path</path>
</image>
</images>
</item>
<items>
【讨论】:
以上是关于将 PHP 关联数组传入和传出 XML的主要内容,如果未能解决你的问题,请参考以下文章