среда, 19 декабря 2007 г.

День пятый (пакет XML)

ЗАДАЧА
Выполнить синтаксический анализ HTML документа, выяснить возможности выполнения XPath запросов.

РЕШЕНИЕ
Некоторое время я потратил на "ложный след" - решил проводить вычистку (xml-изацию) документа с помощью JTidy. В связи с чем поставил rJava. К сожалению, это пакет не очень продуман в плане удобства пользования - пользователь обязывается использовать соглашения JNI для именования типов, например,

> .jcall(f, "Ljava/awt/Component;", "add", .jcast(b, "java/awt/Component"))
и делается это непоследовательно - есть разница в объявлении типа для .jcall и.jcast. Также эти коварные ';'. От пользователя требуется помнить про зоопарк (или иметь под рукой)
I integer D double (numeric) J long (*)  F float (*)
V void Z boolean   C char (integer)  B byte (raw)
и соглашения для массивов: [L/java/lang/String. Видимо из - за разных моделей типизации в R и Java, не реализовано отслеживание наследования Java - классов, поэтому код
...
> in <- .jnew("java/io/ByteArrayInputStream")
> .jcall(tidy, "Lorg/w3c/tidy/Node;", "parse", in, out)
не работает, поскольку требует явного приведения:
> .jcall(tidy, "Lorg/w3c/tidy/Node;", "parse", 
        .jcast(in,"java/io/InputStream"),  
        .jcast(out,"java/io/OutputStream"))
Так что, промежуточный вывод такой - при работе с rJava необходимо как можно больше кода писать на Java (Groovy? - интересный опыт, но что - то есть сомнения в успешности), оставляя на стороне R самый минимум. Что, в общем, очевидно.

Спустя некоторое время обнаружил, что в доках на пакеты в разделе Usage могут перечисляться не только синонимы имён функций, но и различные функции, а пакет XML реализует всю необходимую функциональность для работы с HTML.
htmlTreeParse(file, ignoreBlanks = TRUE, handlers = NULL,
              replaceEntities = FALSE, asText = FALSE, 
              trim = TRUE, isURL = FALSE, asTree = FALSE,
              useInternalNodes = FALSE, encoding = character(),
              useDotNames = length(grep("^\.", names(handlers))) > 0,
              xinclude = FALSE, addFinalizer = TRUE) 
парсит документ, представленный в виде дискового файла (возможно сжатого), URL, строки текста.

Задачу решает следующий код:
...
> doc <- htmlTreeParse(file, useInternalNodes=T)
> scnd_table <- getNodeSet(doc, "/html/body/table[2]")
> length(scnd_table)
1
> names(scnd_table[[1]])
ВЫВОД
Пакет XML- превосходная работа! Есть возможность обращения к удалённому документу, выполнения XPath запросов к содержимому, DOM и SAX механизмы обработки. Определённо, если я возьмусь делать свой "Большой Проект", он будет на R.

Комментариев нет: