【问题标题】:Flex 4.6 - XML appendChild unexpected behaviourFlex 4.6 - XML appendChild 意外行为
【发布时间】:2011-12-14 13:28:27
【问题描述】:

我想使用 XML 为我的应用中的元素保存一些配置。 在我的示例中,我想将 6 个附加配置集添加到一个“主要”XML。每组可以是 config1 或 config2。 在这种情况下,我添加了 3x config1 和 3x config2。如果我跟踪我的结果,我不仅会得到错误的元素顺序,还会得到一些“奇怪的”绑定行为。 当然这是一个简化的例子。我的配置集更复杂(这就是为什么我为每个配置使用单独的 xml 对象)。

谁能告诉我这应该如何工作?

谢谢, 四字

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
           xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="160" creationComplete="init();">

<fx:Declarations>
    <fx:XML id="mainConfig" format="e4x">
        <allConfigSets>
            <viewconfig>Baseconfig</viewconfig>
        </allConfigSets>
    </fx:XML>

    <fx:XML id="configSet1" format="e4x">
        <configSet><viewconfig>Set1</viewconfig></configSet>
    </fx:XML>

    <fx:XML id="configSet2" format="e4x">
        <configSet><viewconfig>Set2</viewconfig></configSet>
    </fx:XML>
</fx:Declarations>

<fx:Script>
    <![CDATA[
        private function init(): void {     

            mainConfig.appendChild(configSet1.viewconfig);
            mainConfig.appendChild(configSet1.viewconfig);
            mainConfig.appendChild(configSet1.viewconfig);
            mainConfig.appendChild(configSet2.viewconfig);
            mainConfig.appendChild(configSet2.viewconfig);
            mainConfig.appendChild(configSet2.viewconfig);

            // trace1 (see below): trace shows wrong order of elements
            trace (mainConfig);

            // trace2:(see below): changing data on original configSet seems to bind into mainConfig
            configSet1.viewconfig = "-";
            trace (mainConfig);
        }
    ]]>
</fx:Script>
</s:Application>

Trace1:
<allConfigSets>
  <viewconfig>Baseconfig</viewconfig>
  <viewconfig>Set1</viewconfig>
  <viewconfig>Set2</viewconfig>
  <viewconfig>Set2</viewconfig>
  <viewconfig>Set2</viewconfig>
  <viewconfig>Set1</viewconfig>
  <viewconfig>Set1</viewconfig>
</allConfigSets>

Trace2:
<allConfigSets>
  <viewconfig>Baseconfig</viewconfig>
  <viewconfig>-</viewconfig>
  <viewconfig>Set2</viewconfig>
  <viewconfig>Set2</viewconfig>
  <viewconfig>Set2</viewconfig>
  <viewconfig>-</viewconfig>
  <viewconfig>-</viewconfig>
</allConfigSets>

使用 AS3 XML 对象并不能解决这个问题:

private function init(): void {     
    var mainConfig:XML = <allConfigSets><viewconfig>0</viewconfig></allConfigSets>
    var configSet1:XML = <configSet><viewconfig>1</viewconfig></configSet>
    var configSet2:XML = <configSet><viewconfig>2</viewconfig></configSet>

    mainConfig.appendChild(configSet1.viewconfig);
    mainConfig.appendChild(configSet1.viewconfig);
    mainConfig.appendChild(configSet1.viewconfig);

    mainConfig.appendChild(configSet2.viewconfig);
    mainConfig.appendChild(configSet2.viewconfig);
    mainConfig.appendChild(configSet2.viewconfig);

    // trace1 (see below): trace shows wrong order of elements
    trace (mainConfig);

    // trace2:(see below): changing data on original configSet seems to bind into mainConfig
    configSet1.viewconfig = "-";
    trace (mainConfig);
}

Trace1:
<allConfigSets>
  <viewconfig>0</viewconfig>
  <viewconfig>1</viewconfig>
  <viewconfig>2</viewconfig>
  <viewconfig>2</viewconfig>
  <viewconfig>2</viewconfig>
  <viewconfig>1</viewconfig>
  <viewconfig>1</viewconfig>
</allConfigSets>

Trace2:
<allConfigSets>
  <viewconfig>0</viewconfig>
  <viewconfig>-</viewconfig>
  <viewconfig>2</viewconfig>
  <viewconfig>2</viewconfig>
  <viewconfig>2</viewconfig>
  <viewconfig>-</viewconfig>
  <viewconfig>-</viewconfig>
</allConfigSets>

【问题讨论】:

    标签: xml apache-flex mobile flex4 appendchild


    【解决方案1】:

    同时发生更改,因为您不断将多个引用附加到完全相同的节点(而不是新节点)。

    这样想(伪代码!):

    <node1>value</node1>
    
    <node2>
        <reference>Go, look at node1!</reference>
        <reference>Go, look at node1!</reference>
        <reference>Go, look at node1!</reference>
    </node2>
    

    每当遇到引用时,都会返回存储在 node1 中的值。当您更改原始值时,由于所有引用都指向同一个节点,它们也将返回相同的新值。

    要附加节点的新副本而不是原始节点,请使用

    mainConfig.appendChild(configSet1.viewconfig.copy());
    

    但请记住,copy() 返回节点的整个子树的副本,而不仅仅是节点本身。

    至于为什么元素的顺序不对,我真的很茫然——XML#appendChild()应该将元素添加到子节点列表的末尾。跟踪(mainConfig.toXMLString()); 是否返回相同的结果?

    【讨论】:

    • 当然我可以看到这里发生了什么,但对我来说问题是:它真的应该这样工作吗?在我看来,一旦将原始对象附加到新对象(在 XML 的情况下),引用原始对象是没有意义的。查看由此产生的订单“错误”,这是否真的是最初的意图是值得怀疑的。无论如何:使用 .copy() 解决了这两个问题。只有当一个对象被多次引用时,才会出现排序问题。非常感谢您的帮助!
    • 它应该以这种方式工作,因为有充分的理由使用引用而不是副本(有些模型需要比简单的树结构更复杂的层次结构)。无论如何,我很高兴它有帮助 - 请接受我的回答,然后:)
    • 我明白你的意思。但如果这应该以这种方式工作,那么 appendChild 也应该与多个实例一起正常工作,而不是在现有节点之间附加它们:-)
    【解决方案2】:

    我猜,当你使用 mxml 来声明 xml 数据时,无论如何它都被认为是 Bindable 的。 您应该在 Actionscript 中使用 XML 对象,然后尝试执行此操作。 这可能是这里的问题,因为在 ActionScript 中,您需要显式使用 [Bindable] 标记才能具有此绑定行为。使用 mxml 会自动将其初始化为可绑定。

    您可以尝试一下并告诉我们吗?

    EIDT 1:看来行为是一致的,我发布的答案不正确。我正在同时寻找解决方案。

    【讨论】:

    • 使用 AS3 XML 对象会导致相同的行为。如果一个 xml 第二次被追加,它不会在末尾追加,而是在 index(1) 上追加。更改原始对象也会自动更改 mainconfig 对象。
    • 这个问题根本与绑定无关。你应该删除这个答案。
    • @weltraumpirat 或者我可以提出替代方法并改为编辑答案。感谢您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 2019-02-07
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 2012-11-28
    • 2012-12-14
    相关资源
    最近更新 更多