繁体   English   中英

如何在FLEX中将XMLList转换为XML

[英]How to convert XMLList to XML in FLEX

我已经引用了以下链接,但找不到适合我的方案的解决方案。

动作3-如何从XMLList转换为XML?

我的xml变量如下:

private var checkXml:XML = new XML(
<universe>
<item name="cat 2">
     <item name = "All"/>
     <item name = "item 1"/>
     <item name = "item 2"/>
  </item>
  <item name="cat 2">
     <item name = "All"/>
     <item name = "item 3"/>
     <item name = "item 4"/>
     <item name = "item 5"/>
     <item name = "item 5"/>
  </item>
  <item name="cat 3">
     <item name = "All 33"/>
     <item name = "item 34"/>
     <item name = "item 44"/>
  </item>
</universe>);

我使用过滤器功能删除上述xml中的重复值,如下所示:

private function filter(xmlSample:XML):XMLList 
{
     var seen:Object={};
     return xmlSample..@name.(!seen[valueOf()]&&(seen[valueOf()]=true));
}

返回XMLList数据。当我使用它获取XML格式为:

var thisXml:XMLList = filter(checkXml);
Alert.show(thisXml.toXMLString());

我没有得到XML格式的输出;我是这样得到的:

     cat 2
     All
     item 1
     item 2
     item 3
     item 4
     item 5
     cat 3
     All 33
     item 34
     item 44

如何在Flex中以XML格式获得与我的XML变量“ checkXml”相同的格式,以便我可以保留所有父节点和子节点,从而删除重复项。

这是一个快速建议:

function clean(xml:XML):XML{
    var paths:Dictionary = new Dictionary(true);//keep track of paths
    var result = new XML("<"+xml.localName()+" />");//make new xml
    for each(var child:XML in xml.*){//travers 1st level
        var path:String = child.parent().localName()+"/"+child.localName()+"@"+child.@name;//get a path (I formatted it like)
        if(!paths[path]) {//if it's a new node
            paths[path] = child;//store it in the dictionary
            result.appendChild(child.copy());//add it to the result
        }else {//otherwise copy children
            for each(var clone:XML in child.*)//check for duplicates, otherwise insert, NOTE this does not merge child nodes yet :(
                if(result[child.localName()][0].*.(@name == clone.@name).length() == 0) result[child.localName()][0].appendChild(clone);
        }
    }
    trace(result.toXMLString());
    return result;
}

有了基本的xml,它就可以完成工作,但是它不是很灵活。 它应该合并子节点以进行重复,也许应该是递归的,但是我没有时间atm。

更新:我还有两个版本供您使用。 一个进入子节点的级别:

function clean(xml:XML):XML{
    var paths:Dictionary = new Dictionary(true);//keep track of 
    var result = new XML("<"+xml.localName()+" />");
    for each(var child:XML in xml.*){
        var path:String = child.parent().localName()+"/"+child.localName()+"@"+child.@name;
        if(!paths[path]) {
            paths[path] = child;
            result.appendChild(child.copy());
        }else
            for each(var clone:XML in child.*)
                if(result[child.localName()][0].*.(@name == clone.@name).length() == 0) result[child.localName()][0].appendChild(clone);
                else result[child.localName()][0].*.(@name == clone.@name)[0].appendChild(clone.*);
    }
    return result;
}

所以这样的xml:

var data:XML = <universe>
<item name="cat 2">
     <item name = "All">
        <item name="item child 1" />
        <item name="item child 3">
            <item name="item grandchild 1" />
        </item>
     </item>
     <item name = "item 1">
        <item name = "item child 1" />
     </item>
     <item name = "item 2"/>
  </item>
  <item name="cat 2">
     <item name = "All">
        <item name="item child 2" />
        <item name="item child 3">
            <item name="item grandchild 2" />
        </item>
     </item>
     <item name = "item 3"/>
     <item name = "item 4"/>
     <item name = "item 5"/>
     <item name = "item 5"/>
  </item>
  <item name="cat 3">
     <item name = "All 33"/>
     <item name = "item 34"/>
     <item name = "item 44"/>
  </item>
</universe>;

产生这样的输出:

<universe>
  <item name="cat 2">
    <item name="All">
      <item name="item child 1"/>
      <item name="item child 3">
        <item name="item grandchild 1"/>
      </item>
      <item name="item child 2"/>
      <item name="item child 3">
        <item name="item grandchild 2"/>
      </item>
    </item>
    <item name="item 1">
      <item name="item child 1"/>
    </item>
    <item name="item 2"/>
    <item name="item 3"/>
    <item name="item 4"/>
    <item name="item 5"/>
  </item>
  <item name="cat 3">
    <item name="All 33"/>
    <item name="item 34"/>
    <item name="item 44"/>
  </item>
</universe>

请注意,根节点中的属性(如果有)将丢失。 也许最好的选择仍然是使用递归,如下所示:

function cleanNodes(nodes:XMLList):XML{
    var parent:XML = nodes.parent();
    var result:XML = new XML("<"+parent.localName()+" />");//copy parent node name
    for each(var a:XML in parent.attributes()) result['@'+a.name()] = parent.attribute(a.name());//and attributes
    //merge duplicates at one level
    var found:Dictionary = new Dictionary(true);
    for each(var child:XML in nodes){
        var name:String = child.@name;
        if(!found[name]) {
            found[name] = child;
            result.appendChild(child);
        }else{//merge
            found[name].appendChild(child.*);
        }
    }
    //recurse
    for each(var kid:XML in result.*){//for each child node
        if(kid.*.length() > 0){//if it has children
            var clean:XML = cleanNodes(kid.*);//get a clean copy of each child node
            delete result.*[kid.childIndex()];//remove the original
            result.appendChild(clean);        //add the cleaned one (replace)
        }
    }
    return result;  
}

我不确定这是否是最干净/最优雅的解决方案,但是它可以工作:

trace(cleanNodes(data.*));

产生:

<universe>
  <item name="cat 2">
    <item name="item 2"/>
    <item name="item 3"/>
    <item name="item 4"/>
    <item name="item 5"/>
    <item name="All">
      <item name="item child 1"/>
      <item name="item child 2"/>
      <item name="item child 3">
        <item name="item grandchild 1"/>
        <item name="item grandchild 2"/>
      </item>
    </item>
    <item name="item 1">
      <item name="item child 1"/>
    </item>
  </item>
  <item name="cat 3">
    <item name="All 33"/>
    <item name="item 34"/>
    <item name="item 44"/>
  </item>
</universe>

请注意,具有相同名称的节点会递归折叠(例如“ All”和“ item child 3”),但不幸的是,该节点的排序方式有点不同。

如果您只想过滤儿童图层,请尝试以下操作:

在此处输入图片说明

<?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" 
           xmlns:mx="library://ns.adobe.com/flex/mx" 
           minWidth="955" minHeight="600" creationComplete="init(event)">
<fx:Script>
    <![CDATA[
        import mx.controls.Alert;
        import mx.events.FlexEvent;
        private var checkXml:XML = new XML(
            <universe>
            <item name="cat 2">
                 <item name = "All"/>
                 <item name = "item 1"/>
                 <item name = "item 2"/>
              </item>
              <item name="cat 2">
                 <item name = "All"/>
                 <item name = "item 3"/>
                 <item name = "item 4"/>
                 <item name = "item 5"/>
                 <item name = "item 5"/>
              </item>
              <item name="cat 3">
                 <item name = "All 33"/>
                 <item name = "item 34"/>
                 <item name = "item 44"/>
              </item>
            </universe>);

        private function filter(xmlSample:XML):XMLList 
        {
            var seen:Object={};
            return xmlSample.item.item.(!seen[@name.valueOf()]&&(seen[@name.valueOf()]=true));
        }

        protected function init(event:FlexEvent):void
        {
            var thisXml:XMLList = filter(checkXml);
            Alert.show(thisXml.toXMLString());
        }

    ]]>
</fx:Script>

</s:Application>

编辑

如果要在分离的两个级别上过滤项目,则可以改用以下功能:

        private function filter(xmlSample:XML):XMLList 
        {
            var seen:Object={};
            var seen_child:Object={};
            return xmlSample.item.(!seen[@name.valueOf()]&&(seen[@name.valueOf()]=true)).item.(!seen_child[@name.valueOf()]&&(seen_child[@name.valueOf()]=true));
        }

在这种情况下,筛选器将擦除第二个节点“ cat 2”,并擦除其余节点中所有子节点中的所有重复项。

编辑2

如果要过滤两个图层并且不想丢失二维结构,请执行以下操作:

        private function filter(xmlSample:XML):XMLList 
        {
            var seen:Object={};
            var firstLevel:XMLList = xmlSample.item.(!seen[@name.valueOf()]&&(seen[@name.valueOf()]=true));

            var secondLevel:XMLListCollection = new XMLListCollection();

            var seen_child:Object={};

            for each (var xmlItem:XML in firstLevel)
            {
                var tempXMLList:XMLList = xmlItem.item.(!seen_child[@name.valueOf()]&&(seen_child[@name.valueOf()]=true));
                xmlItem.setChildren(tempXMLList);
                secondLevel.addItem(xmlItem);
            }

            return secondLevel.source;
        }

结果:

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM