2010-04-14 18 views
0

J'utilise tDom pour faire une boucle sur du XML et extraire le texte de chaque élément().TCL tDom Tag XML vide

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

Mais quand il essaie d'imprimer le vendeur, qui est vide, il thows l'erreur nom de la commande non valide « ». Comment puis-je ignorer cela et juste mettre $ nVendor à une chaîne vide?

Répondre

4

La méthode selectNodes d'un noeud renvoie une liste de noeuds qui correspondent à votre modèle. Lorsque vous utilisez directement les résultats comme une commande

set nName [$node selectNodes name/text()] 
puts [$nType data] 

ce que vous faites vraiment est en profitant du fait qu'une liste de 1 point (le nombre de name articles) est identique à celui d'un élément. Quand il n'y a pas de noeuds correspondants, vous revenez une liste vide

set nVendor [$node selectNodes attributes/vendor/text()] ;# -> {} 

et, lorsque vous appelez cela, il est lancer une erreur parce que vous appelez une commande avec le nom {}.

set nVendor [$node selectNodes attributes/vendor/text()] ;# -> {} 
puts [$nVendor data] ;# -> winds up calling 
{} data 

Comme l'a souligné Hai Vu, vous pouvez tester qu'il y avait un résultat en vérifiant le résultat contre "". Une façon « plus correcte » serait probablement de le vérifier avec la liste vide

set nVendor [$node selectNodes attributes/vendor/text()] 
if {[llength $nVendor] == 1} { 
    puts [$nVendor data] 
} 

ou, pour être encore plus complet (si vous n'êtes pas sûr de la XML d'entrée)

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" 
    } 
} 
+0

Si vous écrivez le XPath légèrement différemment, vous pouvez garantir qu'il y aura exactement 0 ou 1 valeur dans la liste des résultats et en utilisant 'llength' pour tester, c'est un op trivial. –

2

Vous pouvez vérifier si $ nVendor est un noeud vide:

if {$nVendor != ""} { 
    puts [$nVendor data] 
} 
+0

préférable d'utiliser 'ne' –

+0

Donal: Merci pour cette directive, je sais maintenant que ne, eq ... devrait être utilisé pour les comparaisons de chaînes et! =, == pour numérique. –