这是一个快速的建议:
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”),但不幸的是节点顺序有点不同。