2017-03-30 3 views
0

J'essaye d'analyser un fichier POM en utilisant Nokogiri, et je veux obtenir les nœuds enfants de premier niveau.Comment obtenir des enfants de premier niveau pour XML en utilisant Nokogiri

Mon fichier POM ressemble à ceci:

<project xmlns="some.maven.link"> 
    <parent> 
    <groupId>parent.jar</groupId> 
    <artifactId>parent-jar</artifactId> 
    </parent>   
    <groupId>child.jar</groupId> 
    <artifactId>child-jar</artifactId> 
</project> 

Je suis en train de chercher le artifactId « enfant-pot », mais le XPath que j'utilise est peut-être incorrecte et il me aller chercher « parent.jar » comme la première occurrence.

Ceci est mon code Ruby:

@pom = Nokogiri::XML(File.open(file_path)) 
p @pom.xpath("/project/artifactId", project"=>"http://maven.apache.org/POM/4.0.0")[0].text 

je peux accéder au deuxième élément, mais que tout serait un hack.

+0

Bien que je n'ai pas les outils pour tester votre code ruby, votre XPath aurait dû renvoyer * only * 'child-jar': http://xpatheval.apphb.com/DI8w0z8D1. – har07

+0

Le problème est l'espace de noms. Il n'est pas référencé dans le sélecteur donc Nokogiri/libXML2 ne sait pas où chercher. –

Répondre

0

Votre exemple XML ne semble pas être correct. Simplifier:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<project> 
    <parent> 
    <groupId>parent.jar</groupId> 
    <artifactId>parent-jar</artifactId> 
    </parent>   
    <groupId>child.jar</groupId> 
    <artifactId>child-jar</artifactId> 
</project> 
EOT 

doc.at('project > artifactId').text # => "child-jar" 

En utilisant XPath j'utiliser:

doc.at('/project/artifactId').text # => "child-jar" 

Je vous suggère d'apprendre la différence entre search, xpath, css et leurs cousines at* qui sont tous documentés dans le "Searching a XML/HTML Document" et Node documentation.

Dans l'exemple ci-dessus, j'ai supprimé les informations de l'espace de noms XML pour simplifier les choses. Les espaces de noms XML sont utiles, mais ils sont également irritants et, dans votre exemple XML, vous l'avez brisé en ne fournissant pas une URL valide. Fixation l'exemple avec:

<project xmlns="http://www.w3.org/1999/xhtml"> 

Je peux utiliser:

namespaces = doc.collect_namespaces # => {"xmlns"=>"http://www.w3.org/1999/xhtml"} 
doc.at('project > artifactId', namespaces).text # => "child-jar" 

ou:

doc.at('xmlns|project > xmlns|artifactId').text # => "child-jar" 

Je préfère et recommande le premier car il est plus lisible et moins bruyant. L'implémentation de CSS dans les sélecteurs de Nokogiri simplifie la plupart des sélecteurs. Passer dans les espaces de noms collectés dans le document simplifie les recherches, que vous utilisiez CSS ou XPath.

Ces travaux aussi:

doc.at('/xmlns:project/xmlns:artifactId').text # => "child-jar" 
doc.at('/foo:project/foo:artifactId', {'foo' => "http://www.w3.org/1999/xhtml"}).text # => "child-jar" 

Notez que la seconde utilise un espace de noms renommé, qui est utile si vous avez affaire à des déclarations xmlns redondantes dans le document et la nécessité de faire la différence entre eux.

Le tutoriel "Namespaces" de Nokogiri est utile.

+0

Merci qui l'a rendu élégant. C'est mon premier coup à ruby ​​!! Donc merci – NinjaCoder