Как отфильтровать отдельные узлы XML? - PullRequest
0 голосов
/ 18 января 2010

Возьмите этот пример 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.(grandParent.@hidden != "true").(grandParent.parent.@hidden != "true").(grandParent.parent.child.@hidden !=true);

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

Ответы [ 2 ]

1 голос
/ 18 января 2010

Вы можете использовать рекурсивную функцию, подобную этой, предполагая, что ваш XML находится в переменной myXML. Делая это таким образом, вы не будете привязаны к имени ваших элементов (т.е. grandParent, parent, child) и не будете ограничены в количестве уровней (то есть вы можете добавить <pet> узел к каждому <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 голосов
/ 18 января 2010

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

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];
}
...