2010-01-18 7 views
0

Prenez cet exemple XML:Comment filtrer les nœuds spécifiques de 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> 

je besoin d'une sorte de filtre pour obtenir une copie de celui-ci où tous les nœuds marqués « cachés » sont supprimés comme ceci:

<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> 

J'ai essayé d'utiliser quelque chose comme celui-ci

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

Mais ce vraiment me donne tout juste le XML d'origine (depuis que je demande la racine où ces conditions sont remplies, je reçois la racine). Je comprends pourquoi mon approche ne fonctionne pas, mais je ne sais pas où aller à partir d'ici.

Répondre

1

Vous pouvez utiliser une fonction récursive comme celui-ci en supposant que votre XML est dans une myXML variable. De cette façon, vous ne seriez pas lié au nom de vos éléments (grandParent, parent, enfant) et vous ne seriez pas limité dans le nombre de niveaux (vous pouvez ajouter un nœud <pet> à chaque nœud <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

Je vois ce que vous faites ici. Une idée si la fonction récursive est plus ou moins efficace que les boucles de suppression dans ma réponse? – invertedSpear

+0

La fonction récursive est environ 30 - 50 fois plus efficace. L'exécution de votre code 50 fois avec ceci comme le XML initial http://pastebin.com/f5f2e944d prend la moyenne de 110ms. La mienne prend 3ms en moyenne. – sberry

+1

Vous pouvez améliorer la vitesse de votre code pour prendre environ 20ms en moyenne en inversant l'ordre de vos 3 pour chaque boucle (donc bouclez d'abord grandParent, puis parent, puis enfant). Si vous ne comprenez pas pourquoi cela augmente la vitesse faites le moi savoir et je peux expliquer. Bien sûr, l'augmentation relative dépend entièrement du nombre de nœuds grandParent et parent avec hidden = "true". Si aucun d'eux n'a caché = "true" alors votre code ne s'exécute pas plus rapidement en réorganisant votre pour chaque boucle. – sberry

0

Alors voici ce que j'ai pu trouver, mais je n'aime pas avoir à boucler. Laissez-moi savoir si vous avez une meilleure façon:

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]; 
} 
Questions connexes