Rev 8306 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
\name{xmlTreeParse}\alias{xmlTreeParse}\alias{htmlTreeParse}\alias{htmlParse}\alias{xmlInternalTreeParse}\alias{xmlNativeTreeParse}\alias{xmlParse}\alias{xmlSchemaParse}\title{XML Parser}\description{Parses an XML or HTML file or string containing XML/HTML content, and generates an Rstructure representing the XML/HTML tree. Use \code{htmlTreeParse} when the content is knownto be (potentially malformed) HTML.This function has numerous parameters/options and operates quite differentlybased on their values.It can create trees in R or using internal C-level nodes, both ofwhich are useful in different contexts.It can perform conversion of the nodes into R objects usingcaller-specified handler functions and this can be used tomap the XML document directly into R data structures,by-passing the conversion to an R-level tree which would thenbe processed recursively or with multiple descents to extract theinformation of interest.\code{xmlParse} and \code{htmlParse} are equivalent to the\code{xmlTreeParse} and \code{htmlTreeParse} respectively,except they both use a default value for the \code{useInternalNodes} parameterof \code{TRUE}, i.e. they working with and return internalnodes/C-level nodes. These can then be searched usingXPath expressions via \code{\link{xpathApply}} and\code{\link{getNodeSet}}.\code{xmlSchemaParse} is a convenience function for parsing an XML schema.}\usage{xmlTreeParse(file, ignoreBlanks=TRUE, handlers=NULL, replaceEntities=FALSE,asText=FALSE, trim=TRUE, validate=FALSE, getDTD=TRUE,isURL=FALSE, asTree = FALSE, addAttributeNamespaces = FALSE,useInternalNodes = FALSE, isSchema = FALSE,fullNamespaceInfo = FALSE, encoding = character(),useDotNames = length(grep("^\\\\.", names(handlers))) > 0,xinclude = TRUE, addFinalizer = TRUE, error = xmlErrorCumulator(),isHTML = FALSE, options = integer(), parentFirst = FALSE)xmlInternalTreeParse(file, ignoreBlanks=TRUE, handlers=NULL, replaceEntities=FALSE,asText=FALSE, trim=TRUE, validate=FALSE, getDTD=TRUE,isURL=FALSE, asTree = FALSE, addAttributeNamespaces = FALSE,useInternalNodes = TRUE, isSchema = FALSE,fullNamespaceInfo = FALSE, encoding = character(),useDotNames = length(grep("^\\\\.", names(handlers))) > 0,xinclude = TRUE, addFinalizer = TRUE, error = xmlErrorCumulator(),isHTML = FALSE, options = integer(), parentFirst = FALSE)xmlNativeTreeParse(file, ignoreBlanks=TRUE, handlers=NULL, replaceEntities=FALSE,asText=FALSE, trim=TRUE, validate=FALSE, getDTD=TRUE,isURL=FALSE, asTree = FALSE, addAttributeNamespaces = FALSE,useInternalNodes = TRUE, isSchema = FALSE,fullNamespaceInfo = FALSE, encoding = character(),useDotNames = length(grep("^\\\\.", names(handlers))) > 0,xinclude = TRUE, addFinalizer = TRUE, error = xmlErrorCumulator(),isHTML = FALSE, options = integer(), parentFirst = FALSE)htmlTreeParse(file, ignoreBlanks=TRUE, handlers=NULL, replaceEntities=FALSE,asText=FALSE, trim=TRUE, validate=FALSE, getDTD=TRUE,isURL=FALSE, asTree = FALSE, addAttributeNamespaces = FALSE,useInternalNodes = FALSE, isSchema = FALSE,fullNamespaceInfo = FALSE, encoding = character(),useDotNames = length(grep("^\\\\.", names(handlers))) > 0,xinclude = TRUE, addFinalizer = TRUE, error = htmlErrorHandler,isHTML = TRUE, options = integer(), parentFirst = FALSE)htmlParse(file, ignoreBlanks = TRUE, handlers = NULL, replaceEntities = FALSE,asText = FALSE, trim = TRUE, validate = FALSE, getDTD = TRUE,isURL = FALSE, asTree = FALSE, addAttributeNamespaces = FALSE,useInternalNodes = TRUE, isSchema = FALSE, fullNamespaceInfo = FALSE,encoding = character(),useDotNames = length(grep("^\\\\.", names(handlers))) > 0,xinclude = TRUE, addFinalizer = TRUE,error = htmlErrorHandler, isHTML = TRUE,options = integer(), parentFirst = FALSE)xmlSchemaParse(file, asText = FALSE, xinclude = TRUE, error = xmlErrorCumulator())}\arguments{\item{file}{ The name of the file containing the XML contents.This can contain ~ which is expanded to the user'shome directory.It can also be a URL. See \code{isURL}.Additionally, the file can be compressed (gzip)and is read directly without the user havingto de-compress (gunzip) it.}\item{ignoreBlanks}{ logical value indicating whethertext elements made up entirely of white space should be includedin the resulting \sQuote{tree}. }\item{handlers}{Optional collection of functionsused to map the different XML nodes to Robjects. Typically, this is a named list of functions,and a closure can be used to provide local data.This provides a way of filtering the tree as it is beingcreated in R, adding or removing nodes, and generally processingthem as they are constructed in the C code.In a recent addition to the package (version 0.99-8),if this is specified as a single function object,we call that function for each node (of any type) in the underlying DOM tree.It is invoked with the new node and its parent node.This applies to regular nodes and also comments, processinginstructions, CDATA nodes, etc. So this function must besufficiently general to handle them all.}\item{replaceEntities}{logical value indicating whether to substitute entity referenceswith their text directly. This should be left as False.The text still appears as the value of the node, but thereis more information about its source, allowing the parse to be reversedwith full reference information.}\item{asText}{logical value indicating that the first argument,\code{file},should be treated as the XML text to parse, not the name ofa file. This allows the contents of documents to be retrievedfrom different sources (e.g. HTTP servers, XML-RPC, etc.) and stilluse this parser.}\item{trim}{whether to strip white space from the beginning and end of text strings.}\item{validate}{logical indicating whether to use a validating parser or not, or in other wordscheck the contents against the DTD specification. If this is true, warningmessages will be displayed about errors in the DTD and/or document, but the parsingwill proceed except for the presence of terminal errors.This is ignored when parsing an HTML document.}\item{getDTD}{logical flag indicating whether the DTD (both internal and external)should be returned along with the document nodes. This changes thereturn type.This is ignored when parsing an HTML document.}\item{isURL}{indicates whether the \code{file} argument refers to a URL(accessible via ftp or http) or a regular file on the system.If \code{asText} is TRUE, this should not be specified.The function attempts to determine whether thedata source is a URL by using \code{\link{grep}}to look for http or ftp at the start of the string.The libxml parser handles the connection to servers,not the R facilities (e.g. \code{\link{scan}}).}\item{asTree}{this only applies when on passes a value forthe \code{handlers} argument and is used then to determinewhether the DOM tree should be returned or the \code{handlers}object.}\item{addAttributeNamespaces}{a logical value indicating whether toreturn the namespace in the names of the attributes within a nodeor to omit them. If this is \code{TRUE}, an attribute such as\code{xsi:type="xsd:string"} is reported with the name\code{xsi:type}.If it is \code{FALSE}, the name of the attribute is \code{type}.}\item{useInternalNodes}{a logical value indicating whetherto call the converter functions with objects of class\code{XMLInternalNode} rather than \code{XMLNode}.This should make things faster as we do not convert thecontents of the internal nodes to R explicit objects.Also, it allows one to access the parent and ancestor nodes.However, since the objects refer to volatile C-level objects,one cannot store these nodes for use in further computations within R.They \dQuote{disappear} after the processing the XML document is completed.If this argument is \code{TRUE} and no handlers are provided, thereturn value is a reference to the internal C-level document pointer.This can be used to do post-processing via XPath expressions using\code{\link{getNodeSet}}.This is ignored when parsing an HTML document.}\item{isSchema}{a logical value indicating whether the documentis an XML schema (\code{TRUE}) and should be parsed as such usingthe built-in schema parser in libxml.}\item{fullNamespaceInfo}{a logical value indicating whetherto provide the namespace URI and prefix on each nodeor just the prefix. The latter (\code{FALSE}) iscurrently the default as that was the original way thepackage behaved. However, using\code{TRUE} is more informative and we will make thisthe default in the future.This is ignored when parsing an HTML document.}\item{encoding}{ a character string (scalar) giving the encoding for thedocument. This is optional as the document should contain its ownencoding information. However, if it doesn't, the caller can specifythis for the parser. If the XML/HTML document does specify its ownencoding that value is used regardless of any value specified by thecaller. (That's just the way it goes!) So this is to be usedas a safety net in case the document does not have an encoding andthe caller happens to know theactual encoding.}\item{useDotNames}{a logical valueindicating whether to use thenewer format for identifying general element function handlerswith the '.' prefix, e.g. .text, .comment, .startElement.If this is \code{FALSE}, then the older formattext, comment, startElement, ...are used. This causes problems when there are indeed nodesnamed text or comment or startElement as anode-specific handler are confused with the correspondinggeneral handler of the same name. Using \code{TRUE}means that your list of handlers should have names that usethe '.' prefix for these general element handlers.This is the preferred way to write new code.}\item{xinclude}{a logical value indicating whetherto process nodes of the form \code{<xi:include xmlns:xi="https://www.w3.org/2001/XInclude">}to insert content from other parts of (potentially different)documents. \code{TRUE} means resolve the external references;\code{FALSE} means leave the node as is.Of course, one can process these nodes oneself after document hasbeen parse using handler functions or working on the DOM.Please note that the syntax for inclusion using XPointeris not the same as XPath and the results can be a littleunexpected and confusing. See the libxml2 documentation for more details.}\item{addFinalizer}{a logical value indicating whether thedefault finalizer routine should be registered tofree the internal xmlDoc when R no longer has a reference to thisexternal pointer object. This is only relevant when\code{useInternalNodes} is \code{TRUE}.}\item{error}{a function that is invoked when the XML parser reportsan error.When an error is encountered, this is called with 7 arguments.See \code{\link{xmlStructuredStop}} for information about theseIf parsing completes and no document is generated, this function iscalled again with only argument which is a character vector oflength 0. This gives the function an opportunity to report all theerrors and raise an exception rather than doing this when it seesth first one.This function can do what it likes with the information.It can raise an R error or let parser continue and potentiallyfind further errors.The default value of this argument supplies a function thatcumulates the errorsIf this is \code{NULL}, the default error handler function in thepackage \code{\link{xmlStructuredStop}} is invoked and this willraise an error in R at that time in R.}\item{isHTML}{a logical value that allows this function to be used for parsing HTML documents.This causes validation and processing of a DTD to be turned off.This is currently experimental so that we can implement\code{htmlParse} with this same function.}\item{options}{an integer value or vector of values that are combined(OR'ed) togetherto specify options for the XML parser. This is the same as the\code{options} parameter for \code{\link{xmlParseDoc}}.}\item{parentFirst}{a logical value for use when we have handlerfunctions and are traversing the tree.This controls whether we processthe node before processing its children, or process the childrenbefore their parent node.}}\details{The \code{handlers} argument is used similarlyto those specified in \link{xmlEventParse}.When an XML tag (element) is processed,we look for a function in this collectionwith the same name as the tag's name.If this is not found, we look for one named\code{startElement}. If this is not found, we use the defaultbuilt in converter.The same works for comments, entity references, cdata, processing instructions,etc.The default entries should be named\code{comment}, \code{startElement},\code{externalEntity},\code{processingInstruction},\code{text}, \code{cdata} and \code{namespace}.All but the last should take the XMLnode as their first argument.In the future, other information may be passed via \dots,for example, the depth in the tree, etc.Specifically, the second argument will be the parent node into which theyare being added, but this is not currently implemented,so should have a default value (\code{NULL}).The \code{namespace} function is called with a single argument whichis an object of class \code{XMLNameSpace}. This contains\describe{\item{id}{the namespace identifier as used toqualify tag names;}\item{uri}{the value of the namespace identifier,i.e. the URIidentifying the namespace.}\item{local}{a logical value indicating whether the definitionis local to the document being parsed.}}One should note that the \code{namespace} handler is called before thenode in which the namespace definition occurs and its children areprocessed. This is different than the other handlers which are calledafter the child nodes have been processed.Each of these functions can return arbitrary values that are thenentered into the tree in place of the default node passed to thefunction as the first argument. This allows the caller to generatethe nodes of the resulting document tree exactly as they wish. If thefunction returns \code{NULL}, the node is dropped from the resultingtree. This is a convenient way to discard nodes having processed theircontents.}\value{By default ( when \code{useInternalNodes} is \code{FALSE},\code{getDTD} is \code{TRUE}, and nohandler functions are provided), the return value is, an object of(S3) class \code{XMLDocument}.This has two fields named \code{doc} and \code{dtd}and are of class \code{DTDList} and \code{XMLDocumentContent} respectively.If \code{getDTD} is \code{FALSE}, only the \code{doc} object is returned.The \code{doc} object has three fields of its own:\code{file}, \code{version} and \code{children}.\item{\code{file}}{The (expanded) name of the file containing the XML.}\item{\code{version}}{A string identifying the version of XML used by the document.}\item{\code{children}}{A list of the XML nodes at the top of the document.Each of these is of class \code{XMLNode}.These are made up of 4 fields.\describe{\item{\code{name}}{The name of the element.}\item{\code{attributes}}{For regular elements, a named listof XML attributes converted from the<tag x="1" y="abc">}\item{\code{children}}{List of sub-nodes.}\item{\code{value}}{Used only for text entries.}}Some nodes specializations of \code{XMLNode}, such as\code{XMLComment}, \code{XMLProcessingInstruction},\code{XMLEntityRef} are used.If the value of the argument getDTD is TRUE and the document refersto a DTD via a top-level DOCTYPE element, the DTD and its informationwill be available in the \code{dtd} field. The second element is alist containing the external and internal DTDs. Each of thesecontains 2 lists - one for element definitions and another for entities. See\code{\link{parseDTD}}.If a list of functions is given via \code{handlers},this list is returned. Typically, these handler functionsshare state via a closure and the resulting updated data structureswhich contain the extracted and processed values from the XMLdocument can be retrieved via a function in this handler list.If \code{asTree} is \code{TRUE}, then the converted tree is returned.What form this takes depends on what the handler functions havedone to process the XML tree.If \code{useInternalNodes} is \code{TRUE} and no handlers arespecified, an object of S3 class \code{XMLInternalDocument} isreturned. This can be used in much the same ways as an\code{XMLDocument}, e.g. with \code{\link{xmlRoot}},\code{\link{docName}} and so on to traverse the tree.It can also be used with XPath queries via \code{\link{getNodeSet}},\code{\link{xpathApply}} and \code{doc["xpath-expression"]}.If internal nodes are used and the internal tree returned directly,all the nodes are returned as-is and no attempt totrim white space, remove \dQuote{empty} nodes (i.e. containing only whitespace), etc. is done. This is potentially quite expensive and so isnot done generally, but should be done during the processingof the nodes. When using XPath queries, such nodes are easilyidentified and/or ignored and so do not cause any difficulties.They do become an issue when dealing with a node's chidrendirectly and so one can use simple filtering techniques such as\code{ xmlChildren(node)[!xmlSApply(node, inherits, "XMLInternalTextNode")]}and even check the \code{\link{xmlValue}} to determine if it contains onlywhite space.\code{ xmlChildren(node)[!xmlSApply(node, function(x) inherit(x,"XMLInternalTextNode")] && trim(xmlValue(x)) == "")}} }\references{\url{http://xmlsoft.org}, \url{https://www.w3.org/XML/}}\author{Duncan Temple Lang <duncan@wald.ucdavis.edu>}\note{Make sure that the necessary 3rd party libraries are available.}\seealso{ \link{xmlEventParse},\code{\link{free}} for releasing the memory whenan \code{XMLInternalDocument} object is returned.}\examples{fileName <- system.file("exampleData", "test.xml", package="XML")# parse the document and return it in its standard format.xmlTreeParse(fileName)# parse the document, discarding comments.xmlTreeParse(fileName, handlers=list("comment"=function(x,...){NULL}), asTree = TRUE)# print the entitiesinvisible(xmlTreeParse(fileName,handlers=list(entity=function(x) {cat("In entity",x$name, x$value,"\n")x}), asTree = TRUE))# Parse some XML text.# Read the text from the filexmlText <- paste(readLines(fileName), "\n", collapse="")print(xmlText)xmlTreeParse(xmlText, asText=TRUE)# with version 1.4.2 we can pass the contents of an XML# stream without pasting them.xmlTreeParse(readLines(fileName), asText=TRUE)# Read a MathML document and convert each node# so that the primary class is# <name of tag>MathML# so that we can use method dispatching when processing# it rather than conditional statements on the tag name.# See plotMathML() in examples/.fileName <- system.file("exampleData", "mathml.xml",package="XML")m <- xmlTreeParse(fileName,handlers=list(startElement = function(node){cname <- paste(xmlName(node),"MathML", sep="",collapse="")class(node) <- c(cname, class(node));node}))# In this example, we extract _just_ the names of the# variables in the mtcars.xml file.# The names are the contents of the <variable># tags. We discard all other tags by returning NULL# from the startElement handler.## We cumulate the names of variables in a character# vector named 'vars'.# We define this within a closure and define the# variable function within that closure so that it# will be invoked when the parser encounters a <variable># tag.# This is called with 2 arguments: the XMLNode object (containing# its children) and the list of attributes.# We get the variable name via call to xmlValue().# Note that we define the closure function in the call and then# create an instance of it by calling it directly as# (function() {...})()# Note that we can get the names by parsing# in the usual manner and the entire document and then executing# xmlSApply(xmlRoot(doc)[[1]], function(x) xmlValue(x[[1]]))# which is simpler but is more costly in terms of memory.fileName <- system.file("exampleData", "mtcars.xml", package="XML")doc <- xmlTreeParse(fileName, handlers = (function() {vars <- character(0) ;list(variable=function(x, attrs) {vars <<- c(vars, xmlValue(x[[1]]));NULL},startElement=function(x,attr){NULL},names = function() {vars})})())# Here we just print the variable names to the console# with a special handler.doc <- xmlTreeParse(fileName, handlers = list(variable=function(x, attrs) {print(xmlValue(x[[1]])); TRUE}), asTree=TRUE)# This should raise an error.try(xmlTreeParse(system.file("exampleData", "TestInvalid.xml", package="XML"),validate=TRUE))\dontrun{# Parse an XML document directly from a URL.# Requires Internet access.xmlTreeParse("https://www.omegahat.net/Scripts/Data/mtcars.xml", asText=TRUE)}counter = function() {counts = integer(0)list(startElement = function(node) {name = xmlName(node)if(name \%in\% names(counts))counts[name] <<- counts[name] + 1elsecounts[name] <<- 1},counts = function() counts)}h = counter()xmlParse(system.file("exampleData", "mtcars.xml", package="XML"), handlers = h)h$counts()f = system.file("examples", "index.html", package = "XML")htmlTreeParse(readLines(f), asText = TRUE)htmlTreeParse(readLines(f))# Same ashtmlTreeParse(paste(readLines(f), collapse = "\n"), asText = TRUE)getLinks = function() {links = character()list(a = function(node, ...) {links <<- c(links, xmlGetAttr(node, "href"))node},links = function()links)}h1 = getLinks()htmlTreeParse(system.file("examples", "index.html", package = "XML"),handlers = h1)h1$links()h2 = getLinks()htmlTreeParse(system.file("examples", "index.html", package = "XML"),handlers = h2, useInternalNodes = TRUE)all(h1$links() == h2$links())# Using flat treestt = xmlHashTree()f = system.file("exampleData", "mtcars.xml", package="XML")xmlTreeParse(f, handlers = list(.startElement = tt[[".addNode"]]))xmlRoot(tt)doc = xmlTreeParse(f, useInternalNodes = TRUE)sapply(getNodeSet(doc, "//variable"), xmlValue)#free(doc)# character set encoding for HTMLf = system.file("exampleData", "9003.html", package = "XML")# we specify the encodingd = htmlTreeParse(f, encoding = "UTF-8")# get a different result if we do not specify any encodingd.no = htmlTreeParse(f)# document with its encoding in the HEAD of the document.d.self = htmlTreeParse(system.file("exampleData", "9003-en.html",package = "XML"))# XXX want to do a test here to see the similarities between d and# d.self and differences between d.no# includef = system.file("exampleData", "nodes1.xml", package = "XML")xmlRoot(xmlTreeParse(f, xinclude = FALSE))xmlRoot(xmlTreeParse(f, xinclude = TRUE))f = system.file("exampleData", "nodes2.xml", package = "XML")xmlRoot(xmlTreeParse(f, xinclude = TRUE))# Errorstry(xmlTreeParse("<doc><a> & < <?pi > </doc>"))# catch the error by type.tryCatch(xmlTreeParse("<doc><a> & < <?pi > </doc>"),"XMLParserErrorList" = function(e) {cat("Errors in XML document\n", e$message, "\n")})# terminate on first errortry(xmlTreeParse("<doc><a> & < <?pi > </doc>", error = NULL))# see xmlErrorCumulator in the XML packagef = system.file("exampleData", "book.xml", package = "XML")doc.trim = xmlInternalTreeParse(f, trim = TRUE)doc = xmlInternalTreeParse(f, trim = FALSE)xmlSApply(xmlRoot(doc.trim), class)# note the additional XMLInternalTextNode objectsxmlSApply(xmlRoot(doc), class)top = xmlRoot(doc)textNodes = xmlSApply(top, inherits, "XMLInternalTextNode")sapply(xmlChildren(top)[textNodes], xmlValue)# Storing nodesf = system.file("exampleData", "book.xml", package = "XML")titles = list()xmlTreeParse(f, handlers = list(title = function(x)titles[[length(titles) + 1]] <<- x))sapply(titles, xmlValue)rm(titles)}\keyword{file}\keyword{IO}