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 reference 和 LoadSaveXML/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(),在这种情况下,您重复之前的操作:
- 获取child人xml个节点
- 遍历每个 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]);
}
}
}
我正在尝试在 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 reference 和 LoadSaveXML/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.
中的白色 spaceNote2 此答案中的示例假定您发布的 xml 在您尝试 [=94] 的草图文件夹中另存为 data.xml =] 中的代码。请随意将其重命名为 XML 文件的实际名称
好的,现在你已经通过了第一级,但是你如何进入下一级呢?实际上并没有那么糟糕。当您遍历每个 child XML 节点时,您可以检查它是否 hasChildren(),在这种情况下,您重复之前的操作:
- 获取child人xml个节点
- 遍历每个 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]);
}
}
}