XML 文档树遍历

XML Document tree traversal

我正在尝试在 mac 上使用处理 3 创建生命进化的可视化表示 - 我正在使用 XML 来组织 tree-like 数据。以下是我组织 XML 代码的方式:

<?xml version="1.0"?>
<A>
    <animal>Bacteria</animal>
    <B>
        <animal>Archea</animal>
        <C>
            <animal>Foraminifera</animal>
            <D>
                <animal>Green Algae</animal>
                <E>
                    Mosses
                </E>
            </D>
            <J>
                <animal>Yeast</animal>
                <animal>Sponges</animal>
                <animal>Corals</animal>
                <K>
                    <L>RoundWorms</L>
                    <V>SchinoDerms</V>
                </K>
            </J>
        </C>
    </B>
</A>

字母代表时间的分支点,"animal"标签是那个特定时间段存在的动物(我必须添加更多信息,例如"time",但我想先解决这个问题)。

我正在尝试遍历 XML 文档,但无法弄清楚如何比第一个 child 节点 ("B") 更进一步。最后,我希望这类似于一棵断点树,动物从各自的时间段分支出来("Bacteria" 从断点 "A" 分支出来,"Archea" 从断点 [=22= 分支出来], 等等 )

我想如果我能弄清楚如何通过第一个 child 我已经准备好了 - 有什么想法吗?

您应该从示例 > 主题 > 高级数据

下的 XML referenceLoadSaveXML/XMLYahooWeather 等示例开始

您可以通过调用 getChilren() 对您的节点进行基本遍历,其中 return 是一个 XML 数组。在这个阶段,循环遍历这个数组并从这个级别的每个 child XML 实例访问数据应该足够简单:

XML xml;
void setup(){

  xml = loadXML("data.xml");
  xml.trim();

  XML[] level0 = xml.getChildren();
  for(int i = 0; i < level0.length; i++){
    println("level0["+i+"]:" + level0[i]);
  }

}

注意 1: 上面的示例适用于 Processing 3,但可能不适用于旧版本,因为 XML API 更改(例如 trim() 函数可能缺失)。 trim() 函数应该删除白色 spaces(新行、制表符等),否则空行可能被视为 XML 节点。始终检查以避免意外,因为 XML.

中的白色 space

Note2 此答案中的示例假定您发布的 xml 在您尝试 [=94] 的草图文件夹中另存为 data.xml =] 中的代码。请随意将其重命名为 XML 文件的实际名称

好的,现在你已经通过了第一级,但是你如何进入下一级呢?实际上并没有那么糟糕。当您遍历每个 child XML 节点时,您可以检查它是否 hasChildren(),在这种情况下,您重复之前的操作:

  1. 获取child人xml个节点
  2. 遍历每个 child xml 节点

(在这个阶段这将是 'grand' children:

XML xml;

void setup(){
  xml = loadXML("data.xml");
  xml.trim();

  XML[] level0 = xml.getChildren();
  for(int i = 0; i < level0.length; i++){
    println("level0["+i+"]:" + level0[i]);

    //we need to go deeper...but can we ?
    if(level0[i].hasChildren()){
      XML[] level1 = level0[i].getChildren();

      for(int j = 0; j < level1.length; j++){
          println("\tlevel1["+j+"]:" + level1[j]);
      }

    }
  }

}

您应该能够安全地重复该过程以进一步深入研究。

随着你越来越深入,有一些有趣的东西可以玩:递归函数。如果您还不熟悉从头开始编写您自己的函数,您应该首先掌握它。

它们与变量有一些共同点:

  • 函数也有类型(称为 return 类型)
  • 函数也有名字

不过主要做的是编一组指令。 根据这些指令的作用,它们可能会或可能不会 return 结果,这决定了函数类型。

最简单的是不 return 任何东西的函数(因此 return 类型是无效的)。您以前可能使用过 void setup(){} ,对吧? :)

函数创建一个单独的范围(在 {} 符号内),因此在函数范围内定义的变量将只在那里可见,除非结果变量在最后被 returned。

函数可以有 0 个或多个 arguments/parameters(将它们视为选项)。 例如 setup() 不需要参数,但是 point() 需要两个(x 和 y)。

递归函数本质上只是一个调用自身的函数(通常使用不同的参数)。

对于您的 XML,您可以使用递归函数向下钻取所有级别:

XML xml;

void setup(){

  xml = loadXML("data.xml");
  xml.trim();

  recursiveTraverse(xml);
}

void recursiveTraverse(XML xml){
  XML[] childNodes = xml.getChildren();
  for(int i = 0; i < childNodes.length; i++){
    println(childNodes[i].getName()+":"+childNodes[i].toString());
    if(childNodes[i].hasChildren()){
      recursiveTraverse(childNodes[i]);
    }
  }
}