0

この次のリンクを既に参照していましたが、シナリオの解決策が見つかりませんでした。

Actionscript 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

私のXML変数「checkXml」と同じように、FlexでXML形式で同じものを取得する方法。これにより、すべての親ノードと子ノードをそのまま保持できるため、重複が削除されます。

4

2 に答える 2

1

ここに簡単な提案があります:

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を使えば、それは仕事をしますが、あまり柔軟ではありません。重複の子ノードをマージする必要があり、おそらく再帰的である必要がありますが、時間の余裕がありません。

更新: さらに 2 つのバージョンがあります。子ノードのレベルに入るもの:

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>

同じ名前のノードが再帰的に折りたたまれていることに注意してください (「すべて」と「アイテムの子 3」のように) が、残念ながらノードの順序が少し異なります。

于 2013-04-08T17:42:29.570 に答える