2010-01-18 4 views
0

Возьмите этот XML пример:Как отфильтровать встроенные узлы XML?

<root> 
    <grandParent GPid="1" hidden="false"> 
    <parent Pid="1" hidden="false"> 
     <child Cid="1" hidden="false"/> 
     <child Cid="2" hidden="true"/> 
    </parent> 
    <parent Pid="2" hidden="false"> 
     <child Cid="3" hidden="false"/> 
     <child Cid="4" hidden="false"/> 
    </parent> 
    </grandParent> 
    <grandParent GPid="2" hidden="false"> 
    <parent Pid="3" hidden="false"> 
     <child Cid="5" hidden="true"/> 
    </parent> 
    <parent Pid="4" hidden="true"> 
     <child Cid="6" hidden="false"/> 
    </parent> 
    </grandParent> 
    <grandParent GPid="3" hidden="true"> 
    <parent Pid="5" hidden="false"> 
     <child Cid="7" hidden="false"/> 
    </parent> 
    </grandParent> 
</root> 

мне нужно какое-то фильтр, чтобы получить копию этого, где отмечены все узлы «скрытые», удаляются так:

<root> 
    <grandParent GPid="1" hidden="false"> 
    <parent Pid="1" hidden="false"> 
     <child Cid="1" hidden="false"/> 
    </parent> 
    <parent Pid="2" hidden="false"> 
     <child Cid="3" hidden="false"/> 
     <child Cid="4" hidden="false"/> 
    </parent> 
    </grandParent> 
    <grandParent GPid="2" hidden="false"> 
    <parent Pid="3" hidden="false"/> 
    </grandParent> 
</root> 

Я пытался использовать что-то как это

var newXML:XML = XML(root.([email protected] != "true").([email protected] != "true").([email protected] !=true); 

Но что на самом деле просто возвращает мне исходный XML (так как я прошу корня, где будут выполнены эти условия я получаю корень). Я понимаю, почему мой подход не работает, но я не знаю, куда идти отсюда.

ответ

1

Вы можете использовать рекурсивную функцию, как это предполагается, что ваш XML в переменной myXML. Таким образом, вы не будете привязаны к имени ваших элементов (т. Е. GrandParent, parent, child), и вы не будете ограничены в количестве уровней (т. Е. Вы можете добавить узел на каждый узел <child>.)

public function removeElements(avXml:XML, avAttributeName:String, avCondition:String) { 

    var lvAttributeValue:String; 
    var lvXml:XML; 

    var lvXmlList:XMLList = new XMLList(); 
    for each(lvXml in avXml.children()) { 
     lvAttributeValue = lvXml.attribute(avAttributeName); 
     if(lvAttributeValue == avCondition) 
      lvXmlList += lvXml; 

     avXml.setChildren(lvXmlList); 
    } 

    for each(var lvXmlChild:XML in avXml.children()) { 
     removeElements(lvXmlChild,avAttributeName,avCondition); 
    } 
} 


removeElements(myXML, "hidden", "false"); 
trace(myXML.toXMLString()); 

<root hidden="false"> 
     <grandParent GPid="1" hidden="false"> 
     <parent Pid="1" hidden="false"> 
      <child Cid="1" hidden="false"/> 
     </parent> 
     <parent Pid="2" hidden="false"> 
      <child Cid="3" hidden="false"/> 
      <child Cid="4" hidden="false"/> 
     </parent> 
     </grandParent> 
     <grandParent GPid="2" hidden="false"> 
     <parent Pid="3" hidden="false"/> 
     </grandParent> 
    </root> 
+0

Я понимаю, что вы здесь делаете. Любая идея, если рекурсивная функция более или менее эффективна, чем циклы delete в моем ответе? – invertedSpear

+0

Рекурсивная функция примерно в 30-50 раз эффективнее. Выполняя свой код 50 раз с этим, поскольку intial XML http://pastebin.com/f5f2e944d занимает среднее значение 110 мс. Шахта занимает 3 мс в среднем. – sberry

+1

Вы можете улучшить скорость своего кода, чтобы получить среднее значение в 20 мс, просто изменив порядок ваших 3 для каждой петли (так что сначала цикл на grandParent, затем родительский, затем дочерний). Если вы не понимаете, почему это повышает скорость, дайте мне знать, и я могу объяснить. Разумеется, относительное увеличение полностью зависит от количества grandParent и родительских узлов со скрытым = «true». Если ни один из них не скрыт = «истина», тогда ваш код не работает быстрее, переупорядочивая ваш для каждого цикла. – sberry

0

Итак, вот что я смог придумать, но мне не нравится, когда нужно зацикливаться. Дайте мне знать, если у вас есть лучший способ:

var newXML:XML = new XML(root); 
var i:uint=0; 
for(i=0;i<newXML.grandparent.parent.child.(@hidden == false).length();i++){ 
    delete newXML.grandparent.parent.child.(@hidden == false)[0]; 
    //always [0] since the list is shortened by 1 each iteration 
} 
for(i=0;i<newXML.grandparent.parent.(@hidden == false).length();i++){ 
    delete newXML.grandparent.parent.(@hidden == false)[0]; 
} 
for(i=0;i<newXML.grandparent.(@hidden == false).length();i++){ 
    delete newXML.grandparent.(@hidden == false)[0]; 
}