如何更新使用数组的SimpleXMLElement [英] How to update SimpleXMLElement using array

查看:138
本文介绍了如何更新使用数组的SimpleXMLElement的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的XML为Flash恩codeR作品:

I have this xml that works for Flash Encoder:

<?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类型的数据。所以,我想要做这样的事情:

And I need to update some of the data depending on the type of xml the user requires. So I want to do something like this:

$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中,我只有将其添加到阵列配置。

I know this tree works, cause I can do it manually, but the problem is that I don't want to do it like that, so if in the future I need to change other think in the xml, I have only to add it to the array configuration.

我该怎么办呢?我可以写一个递归函数来做到这一点,但我真的不希望做的那样。是否有任何其他方式做到这一点?我不知道......可能是这样的:

How can I do it? I can write a recursive function to do it, but I don't really want to do it in that way. Is there any other way to do it? I don't know... may be something like:

$xml->updateFromArray($data);

由于我再说一遍,我可以编写功能和扩展的SimpleXMLElement,但如果有任何其他本机PHP的方法做它,它​​会更好。

As I repeat, I can write that function and extend SimpleXMLElement, but if there is any other native php method to do it, it will be better.

推荐答案

考虑 $ XML 是文档元素为的SimpleXMLElement $数据是阵列(如问题),如果你担心孩子的编号,例如:元数据,我把它在阵列中的编号是这样的:

Considering $xml is the document element as a SimpleXMLElement and $data is your array (as in the question), if you are concerned about numbering children, e.g. for metadata, I have it numbered in the array this way:

'metadata' => array(
    'entry' => array(
        5 => array(
            'value' => 'Sunny Days',
        ),
    ),
),

下面显示了如何用栈的帮助来解决问题以非递归的方式:

The following shows how to solve the problem in a non-recursive manner with the help of a stack:

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);
    }
}

一些注意事项:


  • 我改变了具体的异常类型删除的依赖。

  • $父[0] == NULL 测试元素 $父不为空(比较/见< A HREF =htt​​p://stackoverflow.com/a/14829309/367456> SimpleXML的类型的cheatsheet )。

  • 作为元素节点放入堆栈供日后提取, $节点[0] 需要被用来设置后,它从堆栈中取出(编号的元素已经在 $节点(默认为第一个),后来去改变它,数 0 需要被用作偏移)。

  • I changed the concrete exception type to remove the dependency.
  • $parent[0] == NULL tests the element $parent is not empty (compare/see SimpleXML Type Cheatsheet).
  • As the element node is put into the stack to be retrieved later, $node[0] needs to be used to set it after it got fetched from the stack (the numbered element is already in $node (the first one by default), to change it later, the number 0 needs to be used as offset).

在线演示

这个例子至今不允许,如果没有,到目前为止它们存在创造新的元素。要添加新的元素中加入抛出不存在的儿童除外:

The example so far does not allow to create new elements if they do not exist so far. To add adding of new elements the exception thrown for nonexisting children:

        if ($parent[0] == NULL) {
            throw new Exception(sprintf("Child-Element '%s' not found.", $element));
        }

需要用一些code,它是将新的儿童,包括第一个被替换:

needs to be replaced with some code that is adding new children including the first one:

        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);
            }
        }

的异常仍然在为的情况下,当添加新的元素,但它的数量比元件加一的现有数大。例如你有4个元素,然后是添加与6号元素,这是不行的。该值是零基础,这通常应该是没有什么问题的。

The exception still in is for the case when a new element is added but it's number is larger than the existing number of elements plus one. e.g. you have got 4 elements and then you "add" the element with the number 6, this won't work. The value is zero-based and this normally should not be any problem.

演示

这篇关于如何更新使用数组的SimpleXMLElement的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆