2013-08-20 13 views
2

Je suis en train d'analyser un fichier XML avec getNodeSet(). Supposons que j'ai un fichier XML d'une librairie avec 4 livres différents répertoriés, mais pour un livre, la balise "authors" est manquante.Analyser XML avec getNodeSet - Identifier les balises manquantes

Si j'analyse le XML pour le tag "authors" en utilisant data.nodes.2 <- getNodeSet(data,'//*/authors'), R renvoie une liste de 3 éléments.

Cependant, ce n'est pas exactement ce que je veux. Comment obtenir "getNodeSet()" pour renvoyer une liste qui a 4 au lieu de trois éléments, c'est-à-dire un élément qui a une valeur manquante où la balise "authors" n'existe pas.

J'apprécie toute aide.

library(XML) 

file <- "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n<!-- Edited by XMLSpy® -->\r\n<bookstore>\r\n<book category=\"cooking\">\r\n<title lang=\"en\">Everyday Italian</title>\r\n<authors>\r\n<author>Giada De Laurentiis</author>\r\n</authors>\r\n<year>2005</year>\r\n<price>30.00</price>\r\n</book>\r\n<book category=\"children\">\r\n<title lang=\"en\">Harry Potter</title>\r\n<authors>\r\n<author>J K. Rowling</author>\r\n</authors>\r\n<year>2005</year>\r\n<price>29.99</price>\r\n</book>\r\n<book category=\"web\">\r\n<title lang=\"en\">XQuery Kick Start</title>\r\n<authors>\r\n<author>James McGovern</author>\r\n<author>Per Bothner</author>\r\n<author>Kurt Cagle</author>\r\n<author>James Linn</author>\r\n<author>Vaidyanathan Nagarajan</author>\r\n</authors>\r\n<year>2003</year>\r\n<price>49.99</price>\r\n</book>\r\n<book category=\"web\" cover=\"paperback\">\r\n<title lang=\"en\">Learning XML</title>\r\n\r\n<year>2003</year>\r\n<price>39.95</price>\r\n</book>\r\n</bookstore>" 

data <- xmlParse(file) 

data.nodes.1 <- getNodeSet(data,'//*/book') 

data.nodes.2 <- getNodeSet(data,'//*/authors') 


# Data 

# <?xml version="1.0" encoding="ISO-8859-1"?> 
# <!-- Edited by XMLSpy® --> 
# <bookstore> 
# <book category="cooking"> 
#  <title lang="en">Everyday Italian</title> 
#  <authors> 
#  <author>Giada De Laurentiis</author> 
#  </authors> 
#  <year>2005</year> 
#  <price>30.00</price> 
# </book> 
# <book category="children"> 
#  <title lang="en">Harry Potter</title> 
#  <authors> 
#  <author>J K. Rowling</author> 
#  </authors> 
#  <year>2005</year> 
#  <price>29.99</price> 
# </book> 
# <book category="web"> 
#  <title lang="en">XQuery Kick Start</title> 
#  <authors> 
#  <author>James McGovern</author> 
#  <author>Per Bothner</author> 
#  <author>Kurt Cagle</author> 
#  <author>James Linn</author> 
#  <author>Vaidyanathan Nagarajan</author> 
#  </authors> 
#  <year>2003</year> 
#  <price>49.99</price> 
# </book> 
# <book category="web" cover="paperback"> 
#  <title lang="en">Learning XML</title> 
#  <year>2003</year> 
#  <price>39.95</price> 
# </book> 
# </bookstore> 

Répondre

3

Une option consiste à utiliser le traitement de la liste de R pour extraire les auteurs de chaque noeud

books <- getNodeSet(doc, "//book") 
authors <- lapply(books, xpathSApply, ".//author", xmlValue) 
authors[sapply(authors, is.list)] <- NA 

et munge que, avec info-niveau comptable

title <- sapply(books, xpathSApply, "string(.//title/text())") 

donnant

>  data.frame(Title=rep(title, sapply(authors, length)), 
+    Author=unlist(authors)) 
       Title     Author 
1 Everyday Italian Giada De Laurentiis 
2  Harry Potter   J K. Rowling 
3 XQuery Kick Start   James McGovern 
4 XQuery Kick Start   Per Bothner 
5 XQuery Kick Start    Kurt Cagle 
6 XQuery Kick Start    James Linn 
7 XQuery Kick Start Vaidyanathan Nagarajan 
8  Learning XML     <NA> 
+0

Merci. Exactement ce dont j'avais besoin. – majom

0

Vous pouvez utiliser la bibliothèque plyr

library(plyr) 
> ldply(xpathApply(data, '//book', getChildrenStrings), rbind) 
       title                authors year price 
1 Everyday Italian             Giada De Laurentiis 2005 30.00 
2  Harry Potter              J K. Rowling 2005 29.99 
3 XQuery Kick Start James McGovernPer BothnerKurt CagleJames LinnVaidyanathan Nagarajan 2003 49.99 
4  Learning XML                <NA> 2003 39.95 
+0

Merci pour votre aide. Cependant, pour une raison que je ne peux malheureusement pas utiliser votre solution: Les auteurs ne sont pas séparés correctement, c'est-à-dire que la dernière lettre du nom des premiers auteurs est attachée à la première lettre du nom du second auteur. – majom

0

Vous pouvez également essayer xmlToDataFrame pour certains XML

x <-xmlToDataFrame(doc) 

Si vous ne voulez pas les auteurs pilées ensemble, vous pouvez parfois résoudre ce problème avec motif correspondant à

x$authors <- gsub("([a-z]{2})([A-Z])", "\\1, \\2", x$authors) 
x 
       title                  authors year price 
1 Everyday Italian               Giada De Laurentiis 2005 30.00 
2  Harry Potter                J K. Rowling 2005 29.99 
3 XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn, Vaidyanathan Nagarajan 2003 49.99 
4  Learning XML                  <NA> 2003 39.95 

D'autres options sont de faire une boucle dans les noeuds du livre (voir? GetNodeSet pour créer et libérer des sous-noeuds) ou de suivre la réponse de Martin (et si vous voulez 4 lignes à la place, essayez ceci)

authors <- sapply(authors, paste, collapse=",") 
data.frame(title, authors) 
Questions connexes