0

我正在使用 tDom 循环遍历一些 XML 并提取每个元素的 text()。

    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 设置为空字符串?

4

2 回答 2

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"
    }
}
于 2010-04-15T13:51:57.027 回答
2

您可以检查 $nVendor 是否为空节点:

if {$nVendor != ""} {
    puts [$nVendor data]
}
于 2010-04-14T23:07:13.420 回答