我有一个适用于Flash编码器的xml:
<?xml version="1.0" encoding="UTF-8"?>
<flashmedialiveencoder_profile>
<preset>
<name></name>
<description></description>
</preset>
<capture>
<video>
<device></device>
<crossbar_input>1</crossbar_input>
<frame_rate>25.00</frame_rate>
<size>
<width></width>
<height></height>
</size>
</video>
<audio>
<device></device>
<crossbar_input>2</crossbar_input>
<sample_rate></sample_rate>
<channels>1</channels>
<input_volume>60</input_volume>
</audio>
</capture>
<encode>
<video>
<format>H.264</format>
<datarate></datarate>
<outputsize></outputsize>
<advanced>
<profile></profile>
<level></level>
<keyframe_frequency>5 Seconds</keyframe_frequency>
</advanced>
<autoadjust>
<enable>false</enable>
<maxbuffersize>1</maxbuffersize>
<dropframes>
<enable>false</enable>
</dropframes>
<degradequality>
<enable>false</enable>
<minvideobitrate></minvideobitrate>
<preservepfq>false</preservepfq>
</degradequality>
</autoadjust>
</video>
<audio>
<format>MP3</format>
<datarate></datarate>
</audio>
</encode>
<restartinterval>
<days></days>
<hours></hours>
<minutes></minutes>
</restartinterval>
<reconnectinterval>
<attempts></attempts>
<interval></interval>
</reconnectinterval>
<output>
<rtmp>
<url></url>
<backup_url></backup_url>
<stream></stream>
</rtmp>
</output>
<metadata>
<entry>
<key>author</key>
<value></value>
</entry>
<entry>
<key>copyright</key>
<value></value>
</entry>
<entry>
<key>description</key>
<value></value>
</entry>
<entry>
<key>keywords</key>
<value></value>
</entry>
<entry>
<key>rating</key>
<value></value>
</entry>
<entry>
<key>title</key>
<value></value>
</entry>
</metadata>
<preview>
<video>
<input>
<zoom>50%</zoom>
</input>
<output>
<zoom>50%</zoom>
</output>
</video>
<audio></audio>
</preview>
<log>
<level>100</level>
<directory></directory>
</log>
</flashmedialiveencoder_profile>我需要根据用户需要的xml类型更新一些数据。所以我想做这样的事情:
$data = array (
'preset' => array (
'name' => 'Low Bandwidth (150 Kbps) - H.264',
),
'capture' => array (
'audio' => array (
'sample_rate' => 44100
)
),
'encode' => array (
'video' => array (
'datarate' => '300;',
'outputsize' => '480x360;',
'advanced' => array (
'profile' => 'Main',
'level' => 2.1,
)
),
'audio' => array (
'datarate' => 48
)
),
);我知道这棵树很有效,因为我可以手动完成,但问题是我不想这样做,所以如果将来我需要更改xml中的其他想法,我只需将其添加到数组配置中。
我该怎么做呢?我可以写一个递归函数来做这件事,但我真的不想这样做。还有没有别的办法呢?我不知道。可能是这样的:
$xml->updateFromArray($data);我重复一遍,我可以编写该函数并扩展SimpleXMLElement,但如果有其他原生php方法可以做到这一点,那就更好了。
发布于 2013-02-13 02:29:32
考虑到$xml是作为SimpleXMLElement的文档元素,而$data是您的数组(如问题中所述),如果您关心对子元素进行编号,例如对元数据进行编号,我会将其在数组中按如下方式编号:
'metadata' => array(
'entry' => array(
5 => array(
'value' => 'Sunny Days',
),
),
),下面是通过堆栈以非递归的方式解决问题的方法:
while (list($set, $node) = array_pop($stack)) {
if (!is_array($set)) {
$node[0] = $set;
continue;
}
foreach ($set as $element => $value) {
$parent = $node->$element;
if ($parent[0] == NULL) {
throw new Exception(sprintf("Child-Element '%s' not found.", $element));
}
$stack[] = array($value, $parent);
}
}一些注意事项:
$parent[0] == NULL测试元素$parent不为空(比较/查看SimpleXML Type Cheatsheet).$node[0]来设置它(编号的元素已经在$node中(默认情况下是第一个),以后要更改它,需要使用0作为偏移量)。还有Online Demo。
到目前为止,这个示例不允许创建新的元素,如果它们目前还不存在。要添加添加新元素,则会为不存在的子级抛出异常:
if ($parent[0] == NULL) {
throw new Exception(sprintf("Child-Element '%s' not found.", $element));
}需要替换为添加新的子代的代码,包括第一个:
if ($parent[0] == NULL) {
if (is_int($element)) {
if ($element != $node->count()) {
throw new Exception(sprintf("Element Number out of order: %d unfitting for %d elements so far.", $element, $node->count()));
}
$node[] = '';
$parent = $node->$element;
} else {
$parent[0] = $node->addChild($element);
}
}仍然存在的例外情况是添加了一个新元素,但它的数量大于现有元素数量加1。例如,你有4个元素,然后你“添加”了数字为6的元素,这是行不通的。该值是从零开始的,这通常不会有任何问题。
Demo
发布于 2013-02-13 00:32:46
我已经让这个对象扩展了SimpleXMLElement,但是如果有更好的方法,我将非常感谢:)
/**
* Object to manipulate and add information to an xml object
*
* @package Stream
* @subpackage SimpleXMLElement
* @author abraham.sustaita@gmail.com
* @author Abraham Cruz
* @version 2 Added functionality to update data with array
* @example $this->rows[0] = array (); now can be edited
*/
class Stream_SimpleXMLElement extends SimpleXMLElement
{
/**
* Method to update the information of the xml
* from an array
*
* @throws Core_Exception
* @param array $array
* @return Stream_SimpleXMLElement
*/
public function updateFromArray(array $array) {
foreach ($array as $key => $data) {
if ($this->$key->count() == 0) {
throw new Core_Exception("The key {$key} does not exists within the XML object.");
} else if ($this->$key->count() > 1) {
foreach ($data as $i => $value) {
$tmpData = &$this->$key;
$tmpkey = &$tmpData [$i];
if (is_array($value)) {
foreach ($value as $key2 => $value2) {
if ($tmpkey->$key2 instanceof Stream_SimpleXMLElement && is_array($value2)) {
$tmpkey->$key2->updateFromArray($value2);
} else {
$tmpkey->$key2 = $value2;
}
}
} else {
$tmpkey = $value;
}
unset ($tmpData, $tmpkey);
}
} else {
if (is_array($data)) {
$this->$key->updateFromArray($data);
} else {
$this->$key = $data;
}
}
}
return $this;
}
}由于object Stream_SimpleXMLElement扩展了SimpleXMLElement,因此该对象的每个子对象都将是Stream_SimpleXMLElement的实例,因此我们可以使用相同的方法...
https://stackoverflow.com/questions/14836849
复制相似问题