2014-09-30 2 views
4

Я пытаюсь найти узлы в html-документе, используя Xpath в R. В приведенном ниже коде я хотел бы знать, как вернуть NULL или NA, когда узел отсутствует:XPath in R: return NA, если узел отсутствует

library(XML) 
b <- ' 
<bookstore specialty="novel"> 
<book style="autobiography"> 
<author> 
<first-name>Joe</first-name> 
<last-name>Bob</last-name> 
</author> 
</book> 
<book style="textbook"> 
<author> 
<first-name>Mary</first-name> 
<last-name>Bob</last-name> 
</author> 
<author> 
<first-name>Britney</first-name> 
<last-name>Bob</last-name> 
</author> 
<price>55</price> 
</book> 
<book style="novel" id="myfave"> 
<author> 
<first-name>Toni</first-name> 
<last-name>Bob</last-name> 
</author> 
</bookstore> 
' 
doc2 <- htmlTreeParse(b, useInternal=T) 
xpathApply(doc2, "//author/first-name", xmlValue) 

например, при запуске функции xpathApply() на автора я хотел бы получить 4 результаты, но если бы я должен был удалить один из <first-name> узлов, я хочу, чтобы функция xpathApply возвращать NULL или что-то иначе на его месте, я не хочу, чтобы он пропустил это. Я хочу, чтобы результат выглядел так, если я должен был удалить <first-name>Mary</first-name>:

Joe 
NA 
Britney 
Tony 
+0

Поддерживает ли R XPath 2.0 ? или всего 1.0? Это поможет определить лучший ответ. – LarsH

+1

@LarsH Уже есть хорошие ответы, но FYI: из прошлых обсуждений на SO (с участием R и XPath), я считаю, что напомнить, что поддерживается только 1.0. –

ответ

4

Вы можете сделать что-то вроде этого:

xpathApply(doc2, "//author", 
      function(x){ 
      if("first-name" %in% names(x)) 
       xmlValue(x[["first-name"]]) 
      else NA}) 

[[1]] 
[1] "Joe" 

[[2]] 
[1] NA 

[[3]] 
[1] "Britney" 

[[4]] 
[1] "Toni" 
+0

Вы могли бы добавить анонимную функцию в выражение регулярного выражения, возможно, grep («Joe»), чтобы xpathApply извлекал значение имени первого имени только в том случае, если в нем было «Joe»? [Я оставляю в стороне contains() на данный момент.] XPath 1.0 не поддерживает регулярное выражение самостоятельно - или неуклюже с translate() - так это обходной путь? – lawyeR

+0

@lawyeR Я боюсь, что я не понимаю, что вы хотите делать. Конечно, вы можете использовать что-то вроде 'if (" first-name "% in% names (x) && grepl (" Joe ", xmlValue (x [[" first-name "]]))' для извлечения имени узел существует, а его значение содержит «Joe». – agstudy

1

Альтернативный метод:

extractFirstName <- function(node) { 
    val <- unlist(xpathApply(node, "first-name", xmlValue)) 
    if (is.null(val)) { val <- NA } 
    val 
} 

xpathApply(doc2, "//author", extractFirstName) 

## [[1]] 
## [1] "Joe" 
## 
## [[2]] 
## [1] NA 
## 
## [[3]] 
## [1] "Britney" 
## 
## [[4]] 
## [1] "Toni" 
Смежные вопросы