我正在使用tDom来遍历一些XML并提取每个元素的文本()。
set xml {
<systems>
<object>
<type>Hardware</type>
<name>Server Name</name>
<attributes>
<vendor></vendor>
</attributes>
</object>
<object>
<type>Hardware</type>
<name>Server Two Name</name>
<attributes>
<vendor></vendor>
</attributes>
</object>
</systems>
};
set doc [dom parse $xml]
set root [$doc documentElement]
set nodeList [$root selectNodes /systems/object]
foreach node $nodeList {
set nType [$node selectNodes type/text()]
set nName [$node selectNodes name/text()]
set nVendor [$node selectNodes attributes/vendor/text()]
# Etc...
puts "Type: "
puts [$nType data]
# Etc ..
puts [$nVendor data]
}
但是当它试图打印出供应商时,它是空的,它会使错误无效的命令名称“”。如何忽略这一点并将$ nVendor设置为空字符串?
答案 0 :(得分:4)
节点的selectNodes
方法返回与您的模式匹配的节点列表。将结果直接用作命令时
set nName [$node selectNodes name/text()]
puts [$nType data]
你真正在做的是利用1项(name
项的数量)的列表与一项相同的事实。如果没有匹配的节点,则会返回一个空列表
set nVendor [$node selectNodes attributes/vendor/text()] ;# -> {}
并且,当你调用它时,它会抛出一个错误,因为你正在调用一个名为{}
的命令。
set nVendor [$node selectNodes attributes/vendor/text()] ;# -> {}
puts [$nVendor data] ;# -> winds up calling
{} data
如Hai Vu所述,您可以通过针对""
检查结果来测试结果。 “更正确”的方法可能是在空列表中检查它
set nVendor [$node selectNodes attributes/vendor/text()]
if {[llength $nVendor] == 1} {
puts [$nVendor data]
}
或者,更完整(如果您不确定输入XML)
set nVendor [$node selectNodes attributes/vendor/text()]
switch -exact -- [llength $nVendor] {
0 {
# no nVendor, do nothing
}
1 {
# 1 vendor, print it
puts [$nVendor data]
}
default {
# weird, we got more than one vendor node... throw an error
error "More than one vendor node"
}
}
答案 1 :(得分:2)
您可以检查$ nVendor是否为空节点:
if {$nVendor != ""} {
puts [$nVendor data]
}