разбор xml для списка в R: как последовательно получать доступ к узлам, когда структура xml меняется?

Задний план

У меня есть файл настроек xml, который может выглядеть так:

<level1>
 <level2>
   <level3>
    <level4name>bob</level4name>
   </level3>
 </level2>
</level1>

но может быть несколько экземпляров level3

<level1>
 <level2>
   <level3>
    <level4name>bob</level4name> 
   </level3>
   <level3>
    <level4name>jack</level4name> 
   </level3>
   <level3>
    <level4name>jill</level4name> 
   </level3>
 </level2>
</level1>

также может быть несколько типов узлов level4 для каждого level3:

   <level3>
    <level4name>bob</level4name> 
    <level4dir>/home/bob/ </level4dir> 
    <level4logical>TRUE</level4logical> 
   </level3>

В R я загружаю этот файл, используя

settings.xml <- xmlTreeParse(settings.file)
settings <- xmlToList(settings.xml)

Я хочу написать скрипт, который преобразует все значения, содержащиеся в level4type1, в вектор уникальных значений на этом уровне, но я в тупике, пытаясь сделать это так, чтобы это работало для всех вышеперечисленных случаев.

Одна из проблем заключается в том, что class(settings[['level2']]) — это список для первых двух случаев и матрица для третьего случая.

> xmlToList(xmlTreeParse('case1.xml'))
$level2.level3.level4name
[1] "bob"
> xmlToList(xmlTreeParse('case2.xml'))
                  level2
level3.level4name "bob" 
level3.level4name "jack"
level3.level4name "jill"
> xmlToList(xmlTreeParse('case3.xml'))
       level2
level3 List,3
level3 List,1
level3 List,1

Вопросы

У меня есть два вопроса:

  1. как я могу извлечь вектор уникальных значений 'level4type1'

  2. Есть лучший способ сделать это?


person David LeBauer    schedule 24.03.2011    source источник
comment
Я подал заявку на на GitHub. Эта проблема связана с альтернативной реализацией xmlToList, которая не демонстрирует такого поведения (но может содержать другие проблемы).   -  person krlmlr    schedule 07.02.2014


Ответы (1)


Попробуйте использовать внутреннее узловое представление XML и очень мощный язык xpath.

> xml = xmlTreeParse("case2.xml", useInternalNodes=TRUE)
> xpathApply(xml, "//level4name", xmlValue)
[[1]]
[1] "bob"

[[2]]
[1] "jack"

[[3]]
[1] "jill"
person Martin Morgan    schedule 24.03.2011
comment
спасибо @Martin, это почти то, что я искал, но у меня все еще есть два вопроса: если узлы не находятся в одной строке, R возвращает \n bob \n, есть ли простой способ обойти это? и есть ли способ вернуть функцию вектор, отличный от использования unlist? - person David LeBauer; 25.03.2011
comment
xpath имеет строковые функции для преобразования; normalize-space удаляет начальные/конечные пробелы. это обеспечивает подсказки, но я думаю, что вам, вероятно, не повезло, за исключением итеративного решения. См. ?xpathSApply для возврата вектора. - person Martin Morgan; 25.03.2011
comment
@David На самом деле, sapply(getNodeSet(xml, "//level4name"), xpathApply, "normalize-space()") сначала получает узлы, а затем нормализует пространство на каждом из них. - person Martin Morgan; 25.03.2011
comment
+1, потому что этот лайнер решил все мои потребности в синтаксическом анализе в обозримом будущем! - person Andrew; 04.12.2012