генерировать вызовы функций для изменения xml с помощью R

Я хотел бы динамически изменять XML-документ с помощью R и xml2: мой подход заключался бы в том, чтобы параметры были готовы в фрейм данных, и просто передать эти параметры функции, которая изменила бы XML-документ.

library(xml2)

doc <- xml2::read_xml('<CATALOG>
<PLANT myid="1">
  <COMMON>Bloodroot</COMMON>
  <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
  <ZONE>4</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$2.44</PRICE>
  <AVAILABILITY>031599</AVAILABILITY>
  </PLANT>
  <PLANT myid="2">
  <COMMON>Columbine</COMMON>
  <BOTANICAL>Aquilegia canadensis</BOTANICAL>
  <ZONE>3</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$9.37</PRICE>
  <AVAILABILITY>030699</AVAILABILITY>
  </PLANT>
  <PLANT myid="3">
  <COMMON>Marsh Marigold</COMMON>
  <BOTANICAL>Caltha palustris</BOTANICAL>
  <ZONE>4</ZONE>
  <LIGHT>Mostly Sunny</LIGHT>
  <PRICE>$6.81</PRICE>
  <AVAILABILITY>051799</AVAILABILITY>
  </PLANT>
  <PLANT myid="4">
  <COMMON>Cowslip</COMMON>
  <BOTANICAL>Caltha palustris</BOTANICAL>
  <ZONE>4</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$9.90</PRICE>
  <AVAILABILITY>030699</AVAILABILITY>
  </PLANT>
  <PLANT myid="5">
  <COMMON>Dutchman\'s-Breeches</COMMON>
  <BOTANICAL>Dicentra cucullaria</BOTANICAL>
  <ZONE>3</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$6.44</PRICE>
  <AVAILABILITY>012099</AVAILABILITY>
  </PLANT>
  <PLANT myid="6">
  <COMMON>Ginger, Wild</COMMON>
  <BOTANICAL>Asarum canadense</BOTANICAL>
  <ZONE>3</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$9.03</PRICE>
  <AVAILABILITY>041899</AVAILABILITY>
  </PLANT>
  <PLANT myid="7">
  <COMMON>Hepatica</COMMON>
  <BOTANICAL>Hepatica americana</BOTANICAL>
  <ZONE>4</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$4.45</PRICE>
  <AVAILABILITY>012699</AVAILABILITY>
  </PLANT>
  </CATALOG>'

)


xpath <-  "//PLANT[@myid='2']"
xml_find_all(doc,xpath)

newxml <- function(xmldoc, xpath, newattr) {

  #
  VarName <- xml2::xml_find_all(xmldoc, xpath)
  xml_attr(VarName, "Name") <- newattr

}

Теперь, если я хочу изменить этот XML-документ, состоящий из тысяч растений, на основе идентификатора (я могу сохранить xpath и новое значение в кадре данных или векторе), как мне действовать?

Я пробовал следующее:

do.call(newxml,list(xmldoc = doc, xpath= dftest$xpath, 
                       newattr = dftest$newname))

Но он не работает, он говорит мне:

 Error in xpath_search(x$node, x$doc, xpath = xpath, nsMap = ns, num_results = Inf) : 
  Expecting a single string value: [type=character; extent=5]. 

Очевидно, есть что-то важное, что мне не хватает в R, но я не могу понять, что, пожалуйста, также не стесняйтесь предлагать лучший подход к этой проблеме.


person M4hd1    schedule 07.09.2018    source источник


Ответы (1)


Похоже, проблема заключается в передаче столбцов фрейма данных в качестве аргументов функции.

Если я передам единичные аргументы, функция, похоже, выдаст результат:

xpath <-  "//PLANT[@myid='2']"
xml_find_all(doc,xpath)
newxml <- function(xmldoc, xpath, newattr) {

  #
  VarName <- xml2::xml_find_all(xmldoc, xpath)
  xml_attr(VarName, "Name") <- newattr

}
do.call(newxml,list(xmldoc = doc, xpath= xpath, 
                    newattr = "TESTING"))

Производит ниже:

 xml_find_all(doc,xpath)
{xml_nodeset (1)}
[1] <PLANT myid="2" Name="TESTING">\n  <COMMON>Columbine</COMMON>\n

Я также думаю, что ваши типы данных в кадре данных являются факторами, а не строками

Я использовал следующее:

newxml <- function(xpath, newattr,xmldoc=doc) {
  VarName <- xml2::xml_find_all(xmldoc, as.character(xpath))
  xml_attr(VarName, "Name") <- as.character(newattr)
}

df <- data.frame(a= c(xpath,xpath),b = c("TEST1","TEST2"))
mapply(newxml,df$a, df$b)

использовать несколько столбцов в качестве переменных с помощью sapply

person RK1    schedule 07.09.2018
comment
Спасибо за ответ RK1, вы были правы, в основном это была ошибка dtype, в то время как я больше сосредоточился на части do.call. Ваш подход к отображению с использованием фрейма данных также интересен. - person M4hd1; 09.09.2018
comment
Отлично --- да, я просто использую mapply, поскольку он напоминает мне о применении и лямбде в Python - person RK1; 09.09.2018