xml2/0000755000176200001440000000000013643540352011141 5ustar liggesusersxml2/NAMESPACE0000644000176200001440000001374713643426060012373 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method("[",xml_missing) S3method("[",xml_nodeset) S3method("[[",xml_missing) S3method("xml_attr<-",xml_missing) S3method("xml_attr<-",xml_node) S3method("xml_attr<-",xml_nodeset) S3method("xml_attrs<-",xml_missing) S3method("xml_attrs<-",xml_node) S3method("xml_attrs<-",xml_nodeset) S3method("xml_name<-",xml_missing) S3method("xml_name<-",xml_node) S3method("xml_name<-",xml_nodeset) S3method("xml_text<-",xml_missing) S3method("xml_text<-",xml_node) S3method("xml_text<-",xml_nodeset) S3method(as.character,xml_document) S3method(as.character,xml_missing) S3method(as.character,xml_node) S3method(as.character,xml_nodeset) S3method(as_list,xml_document) S3method(as_list,xml_missing) S3method(as_list,xml_node) S3method(as_list,xml_nodeset) S3method(as_xml_document,character) S3method(as_xml_document,connection) S3method(as_xml_document,list) S3method(as_xml_document,raw) S3method(as_xml_document,response) S3method(as_xml_document,xml_document) S3method(as_xml_document,xml_node) S3method(as_xml_document,xml_nodeset) S3method(format,xml_node) S3method(is.na,xml_missing) S3method(is.na,xml_node) S3method(is.na,xml_nodeset) S3method(nodeset_apply,xml_document) S3method(nodeset_apply,xml_missing) S3method(nodeset_apply,xml_node) S3method(nodeset_apply,xml_nodeset) S3method(print,xml_document) S3method(print,xml_missing) S3method(print,xml_namespace) S3method(print,xml_node) S3method(print,xml_nodeset) S3method(read_html,default) S3method(read_html,response) S3method(read_xml,character) S3method(read_xml,connection) S3method(read_xml,raw) S3method(read_xml,response) S3method(tree_structure,xml_missing) S3method(tree_structure,xml_node) S3method(tree_structure,xml_nodeset) S3method(write_html,xml_document) S3method(write_html,xml_missing) S3method(write_html,xml_node) S3method(write_html,xml_nodeset) S3method(write_xml,xml_document) S3method(write_xml,xml_missing) S3method(write_xml,xml_node) S3method(write_xml,xml_nodeset) S3method(xml_add_child,xml_document) S3method(xml_add_child,xml_missing) S3method(xml_add_child,xml_node) S3method(xml_add_child,xml_nodeset) S3method(xml_add_parent,xml_missing) S3method(xml_add_parent,xml_node) S3method(xml_add_parent,xml_nodeset) S3method(xml_add_sibling,xml_missing) S3method(xml_add_sibling,xml_node) S3method(xml_add_sibling,xml_nodeset) S3method(xml_attr,xml_missing) S3method(xml_attr,xml_node) S3method(xml_attr,xml_nodeset) S3method(xml_attrs,xml_missing) S3method(xml_attrs,xml_node) S3method(xml_attrs,xml_nodeset) S3method(xml_double,xml_missing) S3method(xml_double,xml_node) S3method(xml_double,xml_nodeset) S3method(xml_find_all,xml_missing) S3method(xml_find_all,xml_node) S3method(xml_find_all,xml_nodeset) S3method(xml_find_chr,xml_missing) S3method(xml_find_chr,xml_node) S3method(xml_find_chr,xml_nodeset) S3method(xml_find_first,xml_node) S3method(xml_find_first,xml_nodeset) S3method(xml_find_lgl,xml_missing) S3method(xml_find_lgl,xml_node) S3method(xml_find_lgl,xml_nodeset) S3method(xml_find_num,xml_missing) S3method(xml_find_num,xml_node) S3method(xml_find_num,xml_nodeset) S3method(xml_integer,xml_missing) S3method(xml_integer,xml_node) S3method(xml_integer,xml_nodeset) S3method(xml_length,xml_missing) S3method(xml_length,xml_node) S3method(xml_length,xml_nodeset) S3method(xml_name,xml_missing) S3method(xml_name,xml_node) S3method(xml_name,xml_nodeset) S3method(xml_ns,xml_document) S3method(xml_ns,xml_missing) S3method(xml_ns,xml_node) S3method(xml_ns,xml_nodeset) S3method(xml_parent,xml_missing) S3method(xml_parent,xml_node) S3method(xml_parent,xml_nodeset) S3method(xml_path,xml_missing) S3method(xml_path,xml_node) S3method(xml_path,xml_nodeset) S3method(xml_remove,xml_missing) S3method(xml_remove,xml_node) S3method(xml_remove,xml_nodeset) S3method(xml_replace,xml_missing) S3method(xml_replace,xml_node) S3method(xml_replace,xml_nodeset) S3method(xml_serialize,xml_document) S3method(xml_serialize,xml_node) S3method(xml_serialize,xml_nodeset) S3method(xml_set_attr,xml_missing) S3method(xml_set_attr,xml_node) S3method(xml_set_attr,xml_nodeset) S3method(xml_set_attrs,xml_missing) S3method(xml_set_attrs,xml_node) S3method(xml_set_attrs,xml_nodeset) S3method(xml_set_name,xml_missing) S3method(xml_set_name,xml_node) S3method(xml_set_name,xml_nodeset) S3method(xml_text,xml_missing) S3method(xml_text,xml_node) S3method(xml_text,xml_nodeset) S3method(xml_type,xml_missing) S3method(xml_type,xml_node) S3method(xml_type,xml_nodeset) S3method(xml_url,xml_missing) S3method(xml_url,xml_node) S3method(xml_url,xml_nodeset) S3method(xml_validate,xml_document) export("xml_attr<-") export("xml_attrs<-") export("xml_name<-") export("xml_text<-") export(as_list) export(as_xml_document) export(download_html) export(download_xml) export(html_structure) export(read_html) export(read_xml) export(url_absolute) export(url_escape) export(url_parse) export(url_relative) export(url_unescape) export(write_html) export(write_xml) export(xml2_example) export(xml_add_child) export(xml_add_parent) export(xml_add_sibling) export(xml_attr) export(xml_attrs) export(xml_cdata) export(xml_child) export(xml_children) export(xml_comment) export(xml_contents) export(xml_double) export(xml_dtd) export(xml_find_all) export(xml_find_chr) export(xml_find_first) export(xml_find_lgl) export(xml_find_num) export(xml_find_one) export(xml_has_attr) export(xml_integer) export(xml_length) export(xml_missing) export(xml_name) export(xml_new_document) export(xml_new_root) export(xml_ns) export(xml_ns_rename) export(xml_ns_strip) export(xml_parent) export(xml_parents) export(xml_path) export(xml_remove) export(xml_replace) export(xml_root) export(xml_serialize) export(xml_set_attr) export(xml_set_attrs) export(xml_set_name) export(xml_set_namespace) export(xml_set_text) export(xml_siblings) export(xml_structure) export(xml_text) export(xml_type) export(xml_unserialize) export(xml_url) export(xml_validate) exportClasses(xml_document) exportClasses(xml_missing) exportClasses(xml_node) exportClasses(xml_nodeset) importFrom(methods,setOldClass) useDynLib(xml2, .registration = TRUE) xml2/tools/0000755000176200001440000000000013516067254012305 5ustar liggesusersxml2/tools/winlibs.R0000644000176200001440000000066613516067254014107 0ustar liggesusers# Build against static libraries from rwinlib VERSION <- commandArgs(TRUE) if(!file.exists(sprintf("../windows/libxml2-%s/include/libxml2/libxml/parser.h", VERSION))){ if(getRversion() < "3.3.0") setInternet2() download.file(sprintf("https://github.com/rwinlib/libxml2/archive/v%s.zip", VERSION), "lib.zip", quiet = TRUE) dir.create("../windows", showWarnings = FALSE) unzip("lib.zip", exdir = "../windows") unlink("lib.zip") } xml2/README.md0000644000176200001440000000415613637645657012447 0ustar liggesusers# xml2 [![R build status](https://github.com/r-lib/xml2/workflows/R-CMD-check/badge.svg)](https://github.com/r-lib/xml2/actions) [![Travis Build Status](https://travis-ci.org/r-lib/xml2.svg?branch=master)](https://travis-ci.org/r-lib/xml2) [![Coverage Status](https://img.shields.io/codecov/c/github/r-lib/xml2/master.svg)](https://codecov.io/github/r-lib/xml2?branch=master) The xml2 package is a binding to [libxml2](http://xmlsoft.org), making it easy to work with HTML and XML from R. The API is somewhat inspired by [jQuery](http://jquery.com). ## Installation You can install xml2 from CRAN, ```R install.packages("xml2") ``` or you can install the development version from github, using `devtools`: ```R # install.packages("devtools") devtools::install_github("r-lib/xml2") ``` ## Usage ```R library("xml2") x <- read_xml(" text ") x xml_name(x) xml_children(x) xml_text(x) xml_find_all(x, ".//baz") h <- read_html("

Hi !") h xml_name(h) xml_text(h) ``` There are three key classes: * `xml_node`: a single node in a document. * `xml_doc`: the complete document. Acting on a document is usually the same as acting on the root node of the document. * `xml_nodeset`: a __set__ of nodes within the document. Operations on `xml_nodeset`s are vectorised, apply the operation over each node in the set. ## Compared to the XML package xml2 has similar goals to the XML package. The main differences are: * xml2 takes care of memory management for you. It will automatically free the memory used by an XML document as soon as the last reference to it goes away. * xml2 has a very simple class hierarchy so don't need to think about exactly what type of object you have, xml2 will just do the right thing. * More convenient handling of namespaces in Xpath expressions - see `xml_ns()` and `xml_ns_strip()` to get started. ## Code of Conduct Please note that the xml2 project is released with a [Contributor Code of Conduct](https://xml2.r-lib.org/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. xml2/man/0000755000176200001440000000000013637645657011735 5ustar liggesusersxml2/man/xml_validate.Rd0000644000176200001440000000123013516067254014654 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_schema.R \name{xml_validate} \alias{xml_validate} \title{Validate XML schema} \usage{ xml_validate(x, schema) } \arguments{ \item{x}{A document, node, or node set.} \item{schema}{an XML document containing the schema} } \value{ TRUE or FALSE } \description{ Validate an XML document against an XML 1.0 schema. } \examples{ # Example from https://msdn.microsoft.com/en-us/library/ms256129(v=vs.110).aspx doc <- read_xml(system.file("extdata/order-doc.xml", package = "xml2")) schema <- read_xml(system.file("extdata/order-schema.xml", package = "xml2")) xml_validate(doc, schema) } xml2/man/xml_type.Rd0000644000176200001440000000060513516067254014051 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_type.R \name{xml_type} \alias{xml_type} \title{Determine the type of a node.} \usage{ xml_type(x) } \arguments{ \item{x}{A document, node, or node set.} } \description{ Determine the type of a node. } \examples{ x <- read_xml(" a ") xml_type(x) xml_type(xml_contents(x)) } xml2/man/xml_missing.Rd0000644000176200001440000000040213516067254014534 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/classes.R \name{xml_missing} \alias{xml_missing} \title{Construct an missing xml object} \usage{ xml_missing() } \description{ Construct an missing xml object } \keyword{internal} xml2/man/xml_attr.Rd0000644000176200001440000000612413631731660014041 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_attr.R \name{xml_attr} \alias{xml_attr} \alias{xml_has_attr} \alias{xml_attrs} \alias{xml_attr<-} \alias{xml_set_attr} \alias{xml_attrs<-} \alias{xml_set_attrs} \title{Retrieve an attribute.} \usage{ xml_attr(x, attr, ns = character(), default = NA_character_) xml_has_attr(x, attr, ns = character()) xml_attrs(x, ns = character()) xml_attr(x, attr, ns = character()) <- value xml_set_attr(x, attr, value, ns = character()) xml_attrs(x, ns = character()) <- value xml_set_attrs(x, value, ns = character()) } \arguments{ \item{x}{A document, node, or node set.} \item{attr}{Name of attribute to extract.} \item{ns}{Optionally, a named vector giving prefix-url pairs, as produced by \code{\link[=xml_ns]{xml_ns()}}. If provided, all names will be explicitly qualified with the ns prefix, i.e. if the element \code{bar} is defined in namespace \code{foo}, it will be called \code{foo:bar}. (And similarly for attributes). Default namespaces must be given an explicit name. The ns is ignored when using \code{\link[=xml_name<-]{xml_name<-()}} and \code{\link[=xml_set_name]{xml_set_name()}}.} \item{default}{Default value to use when attribute is not present.} \item{value}{character vector of new value.} } \value{ \code{xml_attr()} returns a character vector. \code{NA} is used to represent of attributes that aren't defined. \code{xml_has_attr()} returns a logical vector. \code{xml_attrs()} returns a named character vector if \code{x} x is single node, or a list of character vectors if given a nodeset } \description{ \code{xml_attrs()} retrieves all attributes values as a named character vector, \verb{xml_attrs() <-} or \code{xml_set_attrs()} sets all attribute values. \code{xml_attr()} retrieves the value of single attribute and \verb{xml_attr() <-} or \code{xml_set_attr()} modifies its value. If the attribute doesn't exist, it will return \code{default}, which defaults to \code{NA}. \code{xml_has_attr()} tests if an attribute is present. } \examples{ x <- read_xml("") xml_attr(x, "id") xml_attr(x, "apple") xml_attrs(x) kids <- xml_children(x) kids xml_attr(kids, "id") xml_has_attr(kids, "id") xml_attrs(kids) # Missing attributes give missing values xml_attr(xml_children(x), "d") xml_has_attr(xml_children(x), "d") # If the document has a namespace, use the ns argument and # qualified attribute names x <- read_xml(' ') doc <- xml_children(x)[[1]] ns <- xml_ns(x) xml_attrs(doc) xml_attrs(doc, ns) # If you don't supply a ns spec, you get the first matching attribute xml_attr(doc, "id") xml_attr(doc, "b:id", ns) xml_attr(doc, "id", ns) # Can set a single attribute with `xml_attr() <-` or `xml_set_attr()` xml_attr(doc, "id") <- "one" xml_set_attr(doc, "id", "two") # Or set multiple attributes with `xml_attrs()` or `xml_set_attrs()` xml_attrs(doc) <- c("b:id" = "one", "f:id" = "two", "id" = "three") xml_set_attrs(doc, c("b:id" = "one", "f:id" = "two", "id" = "three")) } xml2/man/xml_children.Rd0000644000176200001440000000450713631515545014664 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_children.R \name{xml_children} \alias{xml_children} \alias{xml_child} \alias{xml_contents} \alias{xml_parents} \alias{xml_siblings} \alias{xml_parent} \alias{xml_length} \alias{xml_root} \title{Navigate around the family tree.} \usage{ xml_children(x) xml_child(x, search = 1, ns = xml_ns(x)) xml_contents(x) xml_parents(x) xml_siblings(x) xml_parent(x) xml_length(x, only_elements = TRUE) xml_root(x) } \arguments{ \item{x}{A document, node, or node set.} \item{search}{For \code{xml_child}, either the child number to return (by position), or the name of the child node to return. If there are multiple child nodes with the same name, the first will be returned} \item{ns}{Optionally, a named vector giving prefix-url pairs, as produced by \code{\link[=xml_ns]{xml_ns()}}. If provided, all names will be explicitly qualified with the ns prefix, i.e. if the element \code{bar} is defined in namespace \code{foo}, it will be called \code{foo:bar}. (And similarly for attributes). Default namespaces must be given an explicit name. The ns is ignored when using \code{\link[=xml_name<-]{xml_name<-()}} and \code{\link[=xml_set_name]{xml_set_name()}}.} \item{only_elements}{For \code{xml_length}, should it count all children, or just children that are elements (the default)?} } \value{ A node or nodeset (possibly empty). Results are always de-duplicated. } \description{ \code{xml_children} returns only elements, \code{xml_contents} returns all nodes. \code{xml_length} returns the number of children. \code{xml_parent} returns the parent node, \code{xml_parents} returns all parents up to the root. \code{xml_siblings} returns all nodes at the same level. \code{xml_child} makes it easy to specify a specific child to return. } \examples{ x <- read_xml(" ") xml_children(x) xml_children(xml_children(x)) xml_siblings(xml_children(x)[[1]]) # Note the each unique node only appears once in the output xml_parent(xml_children(x)) # Mixed content x <- read_xml(" a c e f") # Childen gets the elements, contents gets all node types xml_children(x) xml_contents(x) xml_length(x) xml_length(x, only_elements = FALSE) # xml_child makes it easier to select specific children xml_child(x) xml_child(x, 2) xml_child(x, "baz") } xml2/man/xml_new_document.Rd0000644000176200001440000000257613631731660015565 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_modify.R \name{xml_new_document} \alias{xml_new_document} \alias{xml_new_root} \title{Create a new document, possibly with a root node} \usage{ xml_new_document(version = "1.0", encoding = "UTF-8") xml_new_root( .value, ..., .copy = inherits(.value, "xml_node"), .version = "1.0", .encoding = "UTF-8" ) } \arguments{ \item{version}{The version number of the document.} \item{encoding}{The character encoding to use in the document. The default encoding is \sQuote{UTF-8}. Available encodings are specified at \url{http://xmlsoft.org/html/libxml-encoding.html#xmlCharEncoding}.} \item{.value}{node to insert.} \item{...}{If named attributes or namespaces to set on the node, if unnamed text to assign to the node.} \item{.copy}{whether to copy the \code{.value} before replacing. If this is \code{FALSE} then the node will be moved from it's current location.} \item{.version}{The version number of the document, passed to \code{xml_new_document(version)}.} \item{.encoding}{The encoding of the document, passed to \code{xml_new_document(encoding)}.} } \value{ A \code{xml_document} object. } \description{ \code{xml_new_document} creates only a new document without a root node. In most cases you should instead use \code{xml_new_root}, which creates a new document and assigns the root node in one step. } xml2/man/url_escape.Rd0000644000176200001440000000101013637645657014336 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_url.R \name{url_escape} \alias{url_escape} \alias{url_unescape} \title{Escape and unescape urls.} \usage{ url_escape(x, reserved = "") url_unescape(x) } \arguments{ \item{x}{A character vector of urls.} \item{reserved}{A string containing additional characters to avoid escaping.} } \description{ Escape and unescape urls. } \examples{ url_escape("a b c") url_escape("a b c", "") url_unescape("a\%20b\%2fc") url_unescape("\%C2\%B5") } xml2/man/xml_set_namespace.Rd0000644000176200001440000000072713516067254015704 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_modify.R \name{xml_set_namespace} \alias{xml_set_namespace} \title{Set the node's namespace} \usage{ xml_set_namespace(.x, prefix = "", uri = "") } \arguments{ \item{.x}{a node} \item{prefix}{The namespace prefix to use} \item{uri}{The namespace URI to use} } \value{ the node (invisibly) } \description{ The namespace to be set must be already defined in one of the node's ancestors. } xml2/man/xml_find_all.Rd0000644000176200001440000000714213631515545014642 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_find.R \name{xml_find_all} \alias{xml_find_all} \alias{xml_find_first} \alias{xml_find_num} \alias{xml_find_chr} \alias{xml_find_lgl} \alias{xml_find_one} \title{Find nodes that match an xpath expression.} \usage{ xml_find_all(x, xpath, ns = xml_ns(x)) xml_find_first(x, xpath, ns = xml_ns(x)) xml_find_num(x, xpath, ns = xml_ns(x)) xml_find_chr(x, xpath, ns = xml_ns(x)) xml_find_lgl(x, xpath, ns = xml_ns(x)) } \arguments{ \item{x}{A document, node, or node set.} \item{xpath}{A string containing a xpath (1.0) expression.} \item{ns}{Optionally, a named vector giving prefix-url pairs, as produced by \code{\link[=xml_ns]{xml_ns()}}. If provided, all names will be explicitly qualified with the ns prefix, i.e. if the element \code{bar} is defined in namespace \code{foo}, it will be called \code{foo:bar}. (And similarly for attributes). Default namespaces must be given an explicit name. The ns is ignored when using \code{\link[=xml_name<-]{xml_name<-()}} and \code{\link[=xml_set_name]{xml_set_name()}}.} } \value{ \code{xml_find_all} always returns a nodeset: if there are no matches the nodeset will be empty. The result will always be unique; repeated nodes are automatically de-duplicated. \code{xml_find_first} returns a node if applied to a node, and a nodeset if applied to a nodeset. The output is \emph{always} the same size as the input. If there are no matches, \code{xml_find_first} will return a missing node; if there are multiple matches, it will return the first only. \code{xml_find_num}, \code{xml_find_chr}, \code{xml_find_lgl} return numeric, character and logical results respectively. } \description{ Xpath is like regular expressions for trees - it's worth learning if you're trying to extract nodes from arbitrary locations in a document. Use \code{xml_find_all} to find all matches - if there's no match you'll get an empty result. Use \code{xml_find_first} to find a specific match - if there's no match you'll get an \code{xml_missing} node. } \section{Deprecated functions}{ \code{xml_find_one()} has been deprecated. Instead use \code{xml_find_first()}. } \examples{ x <- read_xml("") xml_find_all(x, ".//baz") xml_path(xml_find_all(x, ".//baz")) # Note the difference between .// and // # // finds anywhere in the document (ignoring the current node) # .// finds anywhere beneath the current node (bar <- xml_find_all(x, ".//bar")) xml_find_all(bar, ".//baz") xml_find_all(bar, "//baz") # Find all vs find one ----------------------------------------------------- x <- read_xml("

Some text.

Some other text.

No bold here!

") para <- xml_find_all(x, ".//p") # If you apply xml_find_all to a nodeset, it finds all matches, # de-duplicates them, and returns as a single list. This means you # never know how many results you'll get xml_find_all(para, ".//b") # xml_find_first only returns the first match per input node. If there are 0 # matches it will return a missing node xml_find_first(para, ".//b") xml_text(xml_find_first(para, ".//b")) # Namespaces --------------------------------------------------------------- # If the document uses namespaces, you'll need use xml_ns to form # a unique mapping between full namespace url and a short prefix x <- read_xml(' ') xml_find_all(x, ".//f:doc") xml_find_all(x, ".//f:doc", xml_ns(x)) } \seealso{ \code{\link[=xml_ns_strip]{xml_ns_strip()}} to remove the default namespaces } xml2/man/read_xml.Rd0000644000176200001440000000742513631731660014007 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_parse.R \name{read_xml} \alias{read_xml} \alias{read_html} \alias{read_xml.character} \alias{read_xml.raw} \alias{read_xml.connection} \title{Read HTML or XML.} \usage{ read_xml(x, encoding = "", ..., as_html = FALSE, options = "NOBLANKS") read_html(x, encoding = "", ..., options = c("RECOVER", "NOERROR", "NOBLANKS")) \method{read_xml}{character}(x, encoding = "", ..., as_html = FALSE, options = "NOBLANKS") \method{read_xml}{raw}( x, encoding = "", base_url = "", ..., as_html = FALSE, options = "NOBLANKS" ) \method{read_xml}{connection}( x, encoding = "", n = 64 * 1024, verbose = FALSE, ..., base_url = "", as_html = FALSE, options = "NOBLANKS" ) } \arguments{ \item{x}{A string, a connection, or a raw vector. A string can be either a path, a url or literal xml. Urls will be converted into connections either using \code{base::url} or, if installed, \code{curl::curl}. Local paths ending in \code{.gz}, \code{.bz2}, \code{.xz}, \code{.zip} will be automatically uncompressed. If a connection, the complete connection is read into a raw vector before being parsed.} \item{encoding}{Specify a default encoding for the document. Unless otherwise specified XML documents are assumed to be in UTF-8 or UTF-16. If the document is not UTF-8/16, and lacks an explicit encoding directive, this allows you to supply a default.} \item{...}{Additional arguments passed on to methods.} \item{as_html}{Optionally parse an xml file as if it's html.} \item{options}{Set parsing options for the libxml2 parser. Zero or more of \Sexpr[results=rd]{xml2:::describe_options(xml2:::xml_parse_options())}} \item{base_url}{When loading from a connection, raw vector or literal html/xml, this allows you to specify a base url for the document. Base urls are used to turn relative urls into absolute urls.} \item{n}{If \code{file} is a connection, the number of bytes to read per iteration. Defaults to 64kb.} \item{verbose}{When reading from a slow connection, this prints some output on every iteration so you know its working.} } \value{ An XML document. HTML is normalised to valid XML - this may not be exactly the same transformation performed by the browser, but it's a reasonable approximation. } \description{ Read HTML or XML. } \section{Setting the "user agent" header}{ When performing web scraping tasks it is both good practice --- and often required --- to set the \href{https://en.wikipedia.org/wiki/User_agent}{user agent} request header to a specific value. Sometimes this value is assigned to emulate a browser in order to have content render in a certain way (e.g. \verb{Mozilla/5.0 (Windows NT 5.1; rv:52.0) Gecko/20100101 Firefox/52.0} to emulate more recent Windows browsers). Most often, this value should be set to provide the web resource owner information on who you are and the intent of your actions like this Google scraping bot user agent identifier: \verb{Googlebot/2.1 (+http://www.google.com/bot.html)}. You can set the HTTP user agent for URL-based requests using \code{\link[httr:set_config]{httr::set_config()}} and \code{\link[httr:user_agent]{httr::user_agent()}}: \code{httr::set_config(httr::user_agent("me@example.com; +https://example.com/info.html"))} \code{\link[httr:set_config]{httr::set_config()}} changes the configuration globally, \code{\link[httr:with_config]{httr::with_config()}} can be used to change configuration temporarily. } \examples{ # Literal xml/html is useful for small examples read_xml("") read_html("Hi<title></html>") read_html("<html><title>Hi") # From a local path read_html(system.file("extdata", "r-project.html", package = "xml2")) \dontrun{ # From a url cd <- read_xml(xml2_example("cd_catalog.xml")) me <- read_html("http://had.co.nz") } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/xml_text.Rd��������������������������������������������������������������������������������0000644�0001762�0000144�00000002306�13516067254�014054� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_text.R \name{xml_text} \alias{xml_text} \alias{xml_text<-} \alias{xml_set_text} \alias{xml_double} \alias{xml_integer} \title{Extract or modify the text} \usage{ xml_text(x, trim = FALSE) xml_text(x) <- value xml_set_text(x, value) xml_double(x) xml_integer(x) } \arguments{ \item{x}{A document, node, or node set.} \item{trim}{If \code{TRUE} will trim leading and trailing spaces.} \item{value}{character vector with replacement text.} } \value{ A character vector, the same length as x. } \description{ \code{xml_text} returns a character vector, \code{xml_double} returns a numeric vector, \code{xml_integer} returns an integer vector. } \examples{ x <- read_xml("<p>This is some text. This is <b>bold!</b></p>") xml_text(x) xml_text(xml_children(x)) x <- read_xml("<x>This is some text. <x>This is some nested text.</x></x>") xml_text(x) xml_text(xml_find_all(x, "//x")) x <- read_xml("<p> Some text </p>") xml_text(x, trim = TRUE) # xml_double() and xml_integer() are useful for extracting numeric attributes x <- read_xml("<plot><point x='1' y='2' /><point x='2' y='1' /></plot>") xml_integer(xml_find_all(x, "//@x")) } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/oldclass.Rd��������������������������������������������������������������������������������0000644�0001762�0000144�00000001260�13631515545�014011� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/S4.R \name{xml_document-class} \alias{xml_document-class} \alias{xml_missing-class} \alias{xml_node-class} \alias{xml_nodeset-class} \title{Register S4 classes} \description{ Classes are exported so they can be re-used within S4 classes, see \code{\link[methods:setOldClass]{methods::setOldClass()}}. \code{xml_document}: a complete document. \code{xml_missing}: a missing object, e.g. for an empty result set. \code{xml_node}: a single node in a document. \code{xml_nodeset}: a \emph{set} of nodes within a document. } \concept{xml_document} \concept{xml_missing} \concept{xml_node} \concept{xml_nodeset} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/url_absolute.Rd����������������������������������������������������������������������������0000644�0001762�0000144�00000001544�13637645657�014730� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_url.R \name{url_absolute} \alias{url_absolute} \alias{url_relative} \title{Convert between relative and absolute urls.} \usage{ url_absolute(x, base) url_relative(x, base) } \arguments{ \item{x}{A character vector of urls relative to that base} \item{base}{A string giving a base url.} } \value{ A character vector of urls } \description{ Convert between relative and absolute urls. } \examples{ url_absolute(c(".", "..", "/", "/x"), "http://hadley.nz/a/b/c/d") url_relative("http://hadley.nz/a/c", "http://hadley.nz") url_relative("http://hadley.nz/a/c", "http://hadley.nz/") url_relative("http://hadley.nz/a/c", "http://hadley.nz/a/b") url_relative("http://hadley.nz/a/c", "http://hadley.nz/a/b/") } \seealso{ \code{\link{xml_url}} to retrieve the URL associated with a document } ������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/xml_comment.Rd�����������������������������������������������������������������������������0000644�0001762�0000144�00000000625�13516067254�014534� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/classes.R \name{xml_comment} \alias{xml_comment} \title{Construct a comment node} \usage{ xml_comment(content) } \arguments{ \item{content}{The comment content} } \description{ Construct a comment node } \examples{ x <- xml_new_document() r <- xml_add_child(x, "root") xml_add_child(r, xml_comment("Hello!")) as.character(x) } �����������������������������������������������������������������������������������������������������������xml2/man/xml_url.Rd���������������������������������������������������������������������������������0000644�0001762�0000144�00000001025�13631515545�013666� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_url.R \name{xml_url} \alias{xml_url} \title{The URL of an XML document} \usage{ xml_url(x) } \arguments{ \item{x}{A node or document.} } \value{ A character vector of length 1. Returns \code{NA} if the name is not set. } \description{ This is useful for interpreting relative urls with \code{\link[=url_relative]{url_relative()}}. } \examples{ catalog <- read_xml(xml2_example("cd_catalog.xml")) xml_url(catalog) x <- read_xml("<foo/>") xml_url(x) } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/url_parse.Rd�������������������������������������������������������������������������������0000644�0001762�0000144�00000001130�13637645657�014213� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_url.R \name{url_parse} \alias{url_parse} \title{Parse a url into its component pieces.} \usage{ url_parse(x) } \arguments{ \item{x}{A character vector of urls.} } \value{ A dataframe with one row for each element of \code{x} and columns: scheme, server, port, user, path, query, fragment. } \description{ Parse a url into its component pieces. } \examples{ url_parse("http://had.co.nz/") url_parse("http://had.co.nz:1234/") url_parse("http://had.co.nz:1234/?a=1&b=2") url_parse("http://had.co.nz:1234/?a=1&b=2#def") } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/download_xml.Rd����������������������������������������������������������������������������0000644�0001762�0000144�00000003335�13631731660�014677� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_parse.R \name{download_xml} \alias{download_xml} \alias{download_html} \title{Download a HTML or XML file} \usage{ download_xml( url, file = basename(url), quiet = TRUE, mode = "wb", handle = curl::new_handle() ) download_html( url, file = basename(url), quiet = TRUE, mode = "wb", handle = curl::new_handle() ) } \arguments{ \item{url}{A character string naming the URL of a resource to be downloaded.} \item{file}{A character string with the name where the downloaded file is saved.} \item{quiet}{If \code{TRUE}, suppress status messages (if any), and the progress bar.} \item{mode}{A character string specifying the mode with which to write the file. Useful values are \code{"w"}, \code{"wb"} (binary), \code{"a"} (append) and \code{"ab"}.} \item{handle}{a curl handle object} } \value{ Path of downloaded file (invisibly). } \description{ Libcurl implementation of \code{C_download} (the "internal" download method) with added support for https, ftps, gzip, etc. Default behavior is identical to \code{\link[=download.file]{download.file()}}, but request can be fully configured by passing a custom \code{\link[curl:handle]{curl::handle()}}. } \details{ The main difference between \code{curl_download} and \code{curl_fetch_disk} is that \code{curl_download} checks the http status code before starting the download, and raises an error when status is non-successful. The behavior of \code{curl_fetch_disk} on the other hand is to proceed as normal and write the error page to disk in case of a non success response. } \examples{ \dontrun{ download_html("http://tidyverse.org/index.html") } } \seealso{ \link[curl:curl_download]{curl_download} } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/xml_dtd.Rd���������������������������������������������������������������������������������0000644�0001762�0000144�00000001661�13516067254�013646� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/classes.R \name{xml_dtd} \alias{xml_dtd} \title{Construct a document type definition} \usage{ xml_dtd(name = "", external_id = "", system_id = "") } \arguments{ \item{name}{The name of the declaration} \item{external_id}{The external ID of the declaration} \item{system_id}{The system ID of the declaration} } \description{ This is used to create simple document type definitions. If you need to create a more complicated definition with internal subsets it is recommended to parse a string directly with \code{read_xml()}. } \examples{ r <- xml_new_root( xml_dtd("html", "-//W3C//DTD XHTML 1.0 Transitional//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")) # Use read_xml directly for more complicated DTD d <- read_xml( '<!DOCTYPE doc [ <!ELEMENT doc (#PCDATA)> <!ENTITY foo " test "> ]> <doc>This is a valid document &foo; !</doc>') } �������������������������������������������������������������������������������xml2/man/as_xml_document.Rd�������������������������������������������������������������������������0000644�0001762�0000144�00000001676�13516067254�015402� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/as_xml_document.R \name{as_xml_document} \alias{as_xml_document} \title{Coerce a R list to xml nodes.} \usage{ as_xml_document(x, ...) } \arguments{ \item{x}{A document, node, or node set.} \item{...}{Needed for compatibility with generic. Unused.} } \description{ This turns an R list into the equivalent XML document. Not all R lists will produce valid XML, in particular there can only be one root node and all child nodes need to be named (or empty) lists. R attributes become XML attributes and R names become XML node names. } \examples{ as_xml_document(list(x = list())) # Nesting multiple nodes as_xml_document(list(foo = list(bar = list(baz = list())))) # attributes are stored as R attributes as_xml_document(list(foo = structure(list(), id = "a"))) as_xml_document(list(foo = list( bar = structure(list(), id = "a"), bar = structure(list(), id = "b")))) } ������������������������������������������������������������������xml2/man/xml_ns_strip.Rd����������������������������������������������������������������������������0000644�0001762�0000144�00000001300�13516067254�014722� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_modify.R \name{xml_ns_strip} \alias{xml_ns_strip} \title{Strip the default namespaces from a document} \usage{ xml_ns_strip(x) } \arguments{ \item{x}{A document, node, or node set.} } \description{ Strip the default namespaces from a document } \examples{ x <- read_xml( "<foo xmlns = 'http://foo.com'> <baz/> <bar xmlns = 'http://bar.com'> <baz/> </bar> </foo>") # Need to specify the default namespaces to find the baz nodes xml_find_all(x, "//d1:baz") xml_find_all(x, "//d2:baz") # After stripping the default namespaces you can find both baz nodes directly xml_ns_strip(x) xml_find_all(x, "//baz") } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/as_list.Rd���������������������������������������������������������������������������������0000644�0001762�0000144�00000003455�13631515545�013653� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/as_list.R \name{as_list} \alias{as_list} \title{Coerce xml nodes to a list.} \usage{ as_list(x, ns = character(), ...) } \arguments{ \item{x}{A document, node, or node set.} \item{ns}{Optionally, a named vector giving prefix-url pairs, as produced by \code{\link[=xml_ns]{xml_ns()}}. If provided, all names will be explicitly qualified with the ns prefix, i.e. if the element \code{bar} is defined in namespace \code{foo}, it will be called \code{foo:bar}. (And similarly for attributes). Default namespaces must be given an explicit name. The ns is ignored when using \code{\link[=xml_name<-]{xml_name<-()}} and \code{\link[=xml_set_name]{xml_set_name()}}.} \item{...}{Needed for compatibility with generic. Unused.} } \description{ This turns an XML document (or node or nodeset) into the equivalent R list. Note that this is \code{as_list()}, not \code{as.list()}: \code{lapply()} automatically calls \code{as.list()} on its inputs, so we can't override the default. } \details{ \code{as_list} currently only handles the four most common types of children that an element might have: \itemize{ \item Other elements, converted to lists. \item Attributes, stored as R attributes. Attributes that have special meanings in R (\code{\link[=class]{class()}}, \code{\link[=comment]{comment()}}, \code{\link[=dim]{dim()}}, \code{\link[=dimnames]{dimnames()}}, \code{\link[=names]{names()}}, \code{\link[=row.names]{row.names()}} and \code{\link[=tsp]{tsp()}}) are escaped with '.' \item Text, stored as a character vector. } } \examples{ as_list(read_xml("<foo> a <b /><c><![CDATA[<d></d>]]></c></foo>")) as_list(read_xml("<foo> <bar><baz /></bar> </foo>")) as_list(read_xml("<foo id = 'a'></foo>")) as_list(read_xml("<foo><bar id='a'/><bar id='b'/></foo>")) } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/xml_replace.Rd�����������������������������������������������������������������������������0000644�0001762�0000144�00000003361�13631731660�014502� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_modify.R \name{xml_replace} \alias{xml_replace} \alias{xml_add_sibling} \alias{xml_add_child} \alias{xml_add_parent} \alias{xml_remove} \title{Modify a tree by inserting, replacing or removing nodes} \usage{ xml_replace(.x, .value, ..., .copy = TRUE) xml_add_sibling(.x, .value, ..., .where = c("after", "before"), .copy = TRUE) xml_add_child(.x, .value, ..., .where = length(xml_children(.x)), .copy = TRUE) xml_add_parent(.x, .value, ...) xml_remove(.x, free = FALSE) } \arguments{ \item{.x}{a document, node or nodeset.} \item{.value}{node to insert.} \item{...}{If named attributes or namespaces to set on the node, if unnamed text to assign to the node.} \item{.copy}{whether to copy the \code{.value} before replacing. If this is \code{FALSE} then the node will be moved from it's current location.} \item{.where}{to add the new node, for \code{xml_add_child} the position after which to add, use \code{0} for the first child. For \code{xml_add_sibling} either \sQuote{"before"} or \sQuote{"after"} indicating if the new node should be before or after \code{.x}.} \item{free}{When removing the node also free the memory used for that node. Note if you use this option you cannot use any existing objects pointing to the node or its children, it is likely to crash R or return garbage.} } \description{ \code{xml_add_sibling()} and \code{xml_add_child()} are used to insert a node as a sibling or a child. \code{xml_add_parent()} adds a new parent in between the input node and the current parent. \code{xml_replace()} replaces an existing node with a new node. \code{xml_remove()} removes a node from the tree. } \details{ Care needs to be taken when using \code{xml_remove()}, } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/xml_path.Rd��������������������������������������������������������������������������������0000644�0001762�0000144�00000000751�13516067254�014026� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_path.R \name{xml_path} \alias{xml_path} \title{Retrieve the xpath to a node} \usage{ xml_path(x) } \arguments{ \item{x}{A document, node, or node set.} } \value{ A character vector. } \description{ This is useful when you want to figure out where nodes matching an xpath expression live in a document. } \examples{ x <- read_xml("<foo><bar><baz /></bar><baz /></foo>") xml_path(xml_find_all(x, ".//baz")) } �����������������������xml2/man/write_xml.Rd�������������������������������������������������������������������������������0000644�0001762�0000144�00000002730�13631731660�014220� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_write.R \name{write_xml} \alias{write_xml} \alias{write_xml.xml_document} \alias{write_html} \alias{write_html.xml_document} \title{Write XML or HTML to disk.} \usage{ write_xml(x, file, ...) \method{write_xml}{xml_document}(x, file, ..., options = "format", encoding = "UTF-8") write_html(x, file, ...) \method{write_html}{xml_document}(x, file, ..., options = "format", encoding = "UTF-8") } \arguments{ \item{x}{A document or node to write to disk. It's not possible to save nodesets containing more than one node.} \item{file}{Path to file or connection to write to.} \item{...}{additional arguments passed to methods.} \item{options}{default: \sQuote{format}. Zero or more of \Sexpr[results=rd]{xml2:::describe_options(xml2:::xml_save_options())}} \item{encoding}{The character encoding to use in the document. The default encoding is \sQuote{UTF-8}. Available encodings are specified at \url{http://xmlsoft.org/html/libxml-encoding.html#xmlCharEncoding}.} } \description{ This writes out both XML and normalised HTML. The default behavior will output the same format which was read. If you want to force output pass \code{option = "as_xml"} or \code{option = "as_html"} respectively. } \examples{ h <- read_html("<p>Hi!</p>") tmp <- tempfile(fileext = ".xml") write_xml(h, tmp, options = "format") readLines(tmp) # write formatted HTML output write_html(h, tmp, options = "format") readLines(tmp) } ����������������������������������������xml2/man/xml_name.Rd��������������������������������������������������������������������������������0000644�0001762�0000144�00000002255�13631515545�014012� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_name.R \name{xml_name} \alias{xml_name} \alias{xml_name<-} \alias{xml_set_name} \title{The (tag) name of an xml element.} \usage{ xml_name(x, ns = character()) xml_name(x, ns = character()) <- value xml_set_name(x, value, ns = character()) } \arguments{ \item{x}{A document, node, or node set.} \item{ns}{Optionally, a named vector giving prefix-url pairs, as produced by \code{\link[=xml_ns]{xml_ns()}}. If provided, all names will be explicitly qualified with the ns prefix, i.e. if the element \code{bar} is defined in namespace \code{foo}, it will be called \code{foo:bar}. (And similarly for attributes). Default namespaces must be given an explicit name. The ns is ignored when using \code{\link[=xml_name<-]{xml_name<-()}} and \code{\link[=xml_set_name]{xml_set_name()}}.} \item{value}{a character vector with replacement name.} } \value{ A character vector. } \description{ The (tag) name of an xml element. Modify the (tag) name of an element } \examples{ x <- read_xml("<bar>123</bar>") xml_name(x) y <- read_xml("<bar><baz>1</baz>abc<foo /></bar>") z <- xml_children(y) xml_name(xml_children(y)) } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/xml_cdata.Rd�������������������������������������������������������������������������������0000644�0001762�0000144�00000000614�13631731660�014141� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/classes.R \name{xml_cdata} \alias{xml_cdata} \title{Construct a cdata node} \usage{ xml_cdata(content) } \arguments{ \item{content}{The CDATA content, does not include \verb{<![CDATA[}} } \description{ Construct a cdata node } \examples{ x <- xml_new_root("root") xml_add_child(x, xml_cdata("<d/>")) as.character(x) } ��������������������������������������������������������������������������������������������������������������������xml2/man/xml_serialize.Rd���������������������������������������������������������������������������0000644�0001762�0000144�00000001726�13631731660�015061� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_serialize.R \name{xml_serialize} \alias{xml_serialize} \alias{xml_unserialize} \title{Serializing XML objects to connections.} \usage{ xml_serialize(object, connection, ...) xml_unserialize(connection, ...) } \arguments{ \item{object}{\R object to serialize.} \item{connection}{an open \link[base]{connection} or (for \code{serialize}) \code{NULL} or (for \code{unserialize}) a raw vector (see \sQuote{Details}).} \item{...}{Additional arguments passed to \code{\link[=read_xml]{read_xml()}}.} } \value{ For \code{serialize}, \code{NULL} unless \code{connection = NULL}, when the result is returned in a raw vector. For \code{unserialize} an \R object. } \description{ Serializing XML objects to connections. } \examples{ library(xml2) x <- read_xml("<a> <b><c>123</c></b> <b><c>456</c></b> </a>") b <- xml_find_all(x, "//b") out <- xml_serialize(b, NULL) xml_unserialize(out) } ������������������������������������������xml2/man/xml2_example.Rd����������������������������������������������������������������������������0000644�0001762�0000144�00000000663�13516067254�014611� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{xml2_example} \alias{xml2_example} \title{Get path to a xml2 example} \usage{ xml2_example(path = NULL) } \arguments{ \item{path}{Name of file. If \code{NULL}, the example files will be listed.} } \description{ xml2 comes bundled with a number of sample files in its \sQuote{inst/extdata} directory. This function makes them easy to access. } �����������������������������������������������������������������������������xml2/man/xml_structure.Rd���������������������������������������������������������������������������0000644�0001762�0000144�00000002504�13631731660�015125� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_structure.R \name{xml_structure} \alias{xml_structure} \alias{html_structure} \title{Show the structure of an html/xml document.} \usage{ xml_structure(x, indent = 2, file = "") html_structure(x, indent = 2, file = "") } \arguments{ \item{x}{HTML/XML document (or part there of)} \item{indent}{Number of spaces to ident} \item{file}{A \link[base]{connection}, or a character string naming the file to print to. If \code{""} (the default), \code{cat} prints to the standard output connection, the console unless redirected by \code{\link[base]{sink}}. If it is \code{"|cmd"}, the output is piped to the command given by \file{cmd}, by opening a pipe connection. } } \description{ Show the structure of an html/xml document without displaying any of the values. This is useful if you want to get a high level view of the way a document is organised. Compared to \code{xml_structure}, \code{html_structure} prints the id and class attributes. } \examples{ xml_structure(read_xml("<a><b><c/><c/></b><d/></a>")) rproj <- read_html(system.file("extdata","r-project.html", package = "xml2")) xml_structure(rproj) xml_structure(xml_find_all(rproj, ".//p")) h <- read_html("<body><p id = 'a'></p><p class = 'c d'></p></body>") html_structure(h) } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/man/xml_ns.Rd����������������������������������������������������������������������������������0000644�0001762�0000144�00000002621�13631515545�013507� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xml_namespaces.R \name{xml_ns} \alias{xml_ns} \alias{xml_ns_rename} \title{XML namespaces.} \usage{ xml_ns(x) xml_ns_rename(old, ...) } \arguments{ \item{x}{A document, node, or node set.} \item{old, ...}{An existing xml_namespace object followed by name-value (old prefix-new prefix) pairs to replace.} } \value{ A character vector with class \code{xml_namespace} so the default display is a little nicer. } \description{ \code{xml_ns} extracts all namespaces from a document, matching each unique namespace url with the prefix it was first associated with. Default namespaces are named \code{d1}, \code{d2} etc. Use \code{xml_ns_rename} to change the prefixes. Once you have a namespace object, you can pass it to other functions to work with fully qualified names instead of local names. } \examples{ x <- read_xml(' <root> <doc1 xmlns = "http://foo.com"><baz /></doc1> <doc2 xmlns = "http://bar.com"><baz /></doc2> </root> ') xml_ns(x) # When there are default namespaces, it's a good idea to rename # them to give informative names: ns <- xml_ns_rename(xml_ns(x), d1 = "foo", d2 = "bar") ns # Now we can pass ns to other xml function to use fully qualified names baz <- xml_children(xml_children(x)) xml_name(baz) xml_name(baz, ns) xml_find_all(x, "//baz") xml_find_all(x, "//foo:baz", ns) str(as_list(x)) str(as_list(x, ns)) } ���������������������������������������������������������������������������������������������������������������xml2/DESCRIPTION������������������������������������������������������������������������������������0000644�0001762�0000144�00000003430�13643540352�012647� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Package: xml2 Title: Parse XML Version: 1.3.1 Authors@R: c(person(given = "Hadley", family = "Wickham", role = "aut", email = "hadley@rstudio.com"), person(given = "Jim", family = "Hester", role = c("aut", "cre"), email = "jim.hester@rstudio.com"), person(given = "Jeroen", family = "Ooms", role = "aut"), person(given = "RStudio", role = "cph"), person(given = "R Foundation", role = "ctb", comment = "Copy of R-project homepage cached as example")) Description: Work with XML files using a simple, consistent interface. Built on top of the 'libxml2' C library. License: GPL (>= 2) URL: https://xml2.r-lib.org/, https://github.com/r-lib/xml2 BugReports: https://github.com/r-lib/xml2/issues Depends: R (>= 3.1.0) Imports: methods Suggests: covr, curl, httr, knitr, magrittr, mockery, rmarkdown, testthat (>= 2.1.0) VignetteBuilder: knitr Encoding: UTF-8 RoxygenNote: 7.1.0 SystemRequirements: libxml2: libxml2-dev (deb), libxml2-devel (rpm) Collate: 'S4.R' 'as_list.R' 'xml_parse.R' 'as_xml_document.R' 'classes.R' 'init.R' 'paths.R' 'utils.R' 'xml_attr.R' 'xml_children.R' 'xml_find.R' 'xml_modify.R' 'xml_name.R' 'xml_namespaces.R' 'xml_path.R' 'xml_schema.R' 'xml_serialize.R' 'xml_structure.R' 'xml_text.R' 'xml_type.R' 'xml_url.R' 'xml_write.R' 'zzz.R' NeedsCompilation: yes Packaged: 2020-04-08 19:57:50 UTC; jhester Author: Hadley Wickham [aut], Jim Hester [aut, cre], Jeroen Ooms [aut], RStudio [cph], R Foundation [ctb] (Copy of R-project homepage cached as example) Maintainer: Jim Hester <jim.hester@rstudio.com> Repository: CRAN Date/Publication: 2020-04-09 06:30:02 UTC ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/build/�����������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�13643426274�012246� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/build/vignette.rds�����������������������������������������������������������������������������0000644�0001762�0000144�00000000316�13643426274�014605� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������b```b`fcd`b2 �1# 'X&/藟]%9h Pm�:I, Q,LHYsSь`wI-HK î?"5lP5,n90{C2K�7(1 棸(\^P4�@btr$$ �r��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/build/xml2.pdf���������������������������������������������������������������������������������0000644�0001762�0000144�00000433617�13643426272�013637� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%PDF-1.5 % 128 0 obj << /Length 963 /Filter /FlateDecode >> stream xڝV[o6~ϯ$ I^`.-6tC8]n 6jCQV,ǡ=";9$vJ;o/3߫;(w '1|*O{`7Yɼ Ϸ?xo!aH$$H ϝQL.͗bG҈F̊>J` z$qةjpJNn&Yݎ+!Lcd]&$oc?F$%X}Wl~a2S �Q?:KۊI+Wd_ӊIKޔfuW2yH.k�I)D98bސ!wJ%>|UۍƎi|m>/2Ejx;F2d*F!G'\V_A 90Îqц!aZ#[ P+ʵ-BB`Ⱦ?S%pCy['\Tpؾ Z(}yk.eB,^ǚB IphsLGxB_7E4S3k;јM,TߑgE\�ƢBދM=7:+Nn;L<#s.L֣9kAAjţ/*޹c S9X0a7(Jj@rnЃVF^noVZzFMd֋(Ј`;Bxvo[؝<G=bDuQF B9X eRb^M7[LCyH\ci͉ _}VUfrHo�mڌ;a&?kIӰG] liɢ{]82) q5D9#G)Wr9 f#fQ2YXa6ܛ'$;!q8o9 endstream endobj 168 0 obj << /Length 794 /Filter /FlateDecode >> stream xMs :ZzLiߒHjYHI 8[$r,ϲ`Y%\>.fg% d[e$"9{0Hn˝ɾ/3I'nOh^ͪlLY|pfh8ϞP 2DGG׈UlPqUfOm[mn{r=ʮuxtl:SSc~6]}讫_` fNHdHDgOCXb y&baj;31z9LG(^|aJ=~"(ݎ_//f9}f;^Ph_i(1LD^.)^!O<'e{Єƙ$}C߮^K}ӯ]mYd�E_n-xF/"7?e1+~F<Y{!jk#Scݻ0^YYhƥ7 ~lR VWc"26 udjܛ)Rk p1F4R6TFg!p<c{@WM9dHń|p~-+pgUrf1j?9Aݩ cw+ZH|YߟCG $? :nK~l8ؓ1ʕ\iM k^/MWTL`MW@Xjce lhShWuCx'͆h%C+bMQZ! j8t endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 809 /Length 1747 /Filter /FlateDecode >> stream xڽߏ۸W1y8,6@ 6)6ejmCm~G:R6CÙ!9\J8a‘H#H;AFY6Ih:Bka aX&tK7:4VXa4s:_8 aî/l>$0YH(LᵈN$HH XR6B-`M*BV"`d`�,,b\^Ct g8&{&@{VmiS(H#/γ `å4x34O p&S./Pc\TN-Qk<h9Ȉ" `F Bt nF;^,bl+t G~Di �N"+K Ba 55d-!e#06$g!OuZ,2`H Ύݎ2J1*<<!sXú9t;>Tqs#NWmeC#MKz-~xUuX: z:<ۙ:z9ulimvh$ YU:GSk}}RNrݭ\(+ վΖ8kD>r>ViBGWv88j]Lk]P45G4NGi^)soUw/WMu3;!? vΫsj.w ^omPtYtA=\޽ONvvCOƾg,+VsoҼjWw$??g@)pCk}{X<׏XW:U oȘu?W>:~?ȅ|xMQ~�(>En#;Gmb^ov39ђ鮀%V=WSo,~c0(ڵPwwb䎡V=I㹒 !i1#)Y{)|ss3PYݶ|_^CY7FC$w5L['b>AJNy>!_|Ȓ$dL M#^CM(4B0 XC}"k~=i{pn vz_q'o |yn s0\8Z54zl؎ЎЎhώhύhύhύhύhύhϏhϏhϏ cn!9_v~)/JFqd{9{DS0](Q` ;0.M稽2 NFp}-`cќ>fw`.-AI@6H`)C@jycI ,!@3Pa#.+#('$ʠrfq9#*!3l.O4 (4 NIg' Z22Єs9<2 !t0TM(ڸ.F~bP_ o Ig?褤6U=?aF̈́`Q( 2^A{9'x-4iArcZ& *cX΢hgJxx n?uˀ5 w2wJW&aFu8!I endstream endobj 207 0 obj << /Length 1689 /Filter /FlateDecode >> stream xڭXo6B@LgVl-ֹ( Ȓ+K~LJQ'x/m=:e=[ /EiD#oƈGzܻRH?.߰>{#GFYfI} GAegĻ6{/ ;]'EbPF g}wt&ăs ixYzb? /,QVPl*rh Ȩ:JRDCwMD޽*塑U9[P NC,X|^ڭnUv܋Opڲ 0B:VFG9ᅓkEb]ո3͎7 Pa8~mi$.@tDfD6⎕+$/F$(Cq<(M;ǦFf(nl J/x P^Vl#ñQ&RWݼ 9I|?ȶ#Tso~D]ՙMb3'P[I!,tQVrI9 1ԼvvY#6x ! ^ڹ(ՏX{si#..\`]!#u["F' ,IQVOޠ(uG),%ߋܒ6MXB,07c]X2bQWW1ke^:3%^Z=?it�K-oY;pepˆ4{I�MQ数nd@}=Bͱfg)WhInnK$*}38 0iIX+^` vJ)`hHlYHx&F\T՘�&ˍUb jLlaGC*p_W=]/ct4ы2˂ŭ̐!<WH 4S a@rvqRyTMj\;LN[eiqNzNmħ9!eUNQڝ\ A8SJ0~uW|Z$jISޝ? @ d:"oi<d![wR29<*4 o`De1oNicU Ō5 vphx%X[j_$ ߛE3cqdע&P�ֹW ۝i\q]^ "0N-'J!ӥ"ރGruf9ZuvcQy1�3]ၯ[-T2(ɉh~p:L>/1 =uڦW- K. FMW"٠s.oӯɚ'k.SQ8A-܃!؅eǁuu& cDzLOCmQ]As4w 5I4Xk v2h?!Z0DO%؛m6�){ 4OK@^t͇@I}Ղ_k fs|~|b}qWgX`{=^\ 00] fsS;*UX!2o?`Mă!ݐ{@ãF Q8}BtZFsԳ`6 QW?X?] endstream endobj 230 0 obj << /Length 1253 /Filter /FlateDecode >> stream xڵWmo6_!x_d fH>tMsmm%Wꤿ~w$e[dK:QgPo; IB:(%:QHIqg;]y?fN8͒WaSb/#$uA<'ی>~N/;*f8>c$= _NWm`>s"/iUnDz*^w$fu*QOdf2̊DY!ZҠ$$>ML̼aH82*_&Vɪz0ؙD^`ײBUm]Z2-:3(Yjˑ{- !S+K @&SOJ3p-ΤX;ٽUfV!󽄋N-4̝Mk%HkQ*, B(XҚ5TZ MkYƒBM)tӽDZYfaG tlȶTZ.&2B)ȪM\}Fk>Q췜t^jN1xH*xפ+1 گ=)ft=%h@QwhTuNI [N3-iF(r"J$Ib^-d_v @̷ YHhvR e.+F)Fc_?m!gB >n&`0 Y]L"buboEd2P46OP벬Am؇=q SsmmhTUc}9;;:U q̄ Jy}z5N=RW/C!?L~.zxcw(a?8~|  HcA..3F`/pi}WӄQlD� qˊɤuc#P*7MOG*cMV280˧,$`:Jm D%<orkIpNpӕXM1 u0ONdf@ةWNGF"|ȟS,e!{r<$OGkKFh.Oﳬ*1WmM݅۴i9*nyDŽS͛5໗&{ uH#̾#"u11ȽH /CCs>ZꝜel4:;nڻx8k"RyT�1[zoj endstream endobj 245 0 obj << /Length 1260 /Filter /FlateDecode >> stream xڭWYo6~/6fx ЇMz`hNQ`wm+S^J!R ?pDs|ϓk4+`zQQȼS%xv)g__c}( )X3V`g#9c<[j/ țMX07'%A`w|oְ(l`<K^ 7BM0FgMojTuSe3˳Q͜lO N\\H/>]\Gb!E]n#dS2?І(8J +r$j|9�ʹi#Uȵ! 7PD]T괚ʎKU3L-BD^ssN�],9ھhA`jn1J Vع/ҭ;(H0}K'g8A #Sz|mP67;'o`Eࢭԡ>fAZ.#X?9, П-iz쾍,a&ʼn"uRE#[-&lpz[ծ{&^ڔr%F*SĺJ +䈑hB)I]e!z8w`EGM>X$n )v@yj:Qۣ2hQ كHN�+06cL'a-2k#/2�0LR4{!Hr #Js64!  RHh.+o#&!͚&͈q v«Ms~mkfapܰӼiVPbU)i6L7͂~X/jYQ(U)+BOO/(+9wi DƘ` ~ڶƺtz uo%=ɝ]{U?"-Jmx[lps2$~BtPlWSr"+>-d-)frݓoֹzl,g.v],K'9I8e]=Ԅ=?x|Ij2N]=Ͷ/?}{o=nֻw{ $_9Dpq~PPJ uκ>X�@2 n\-&'dtH n&b/E0X{{|@zk,O?͊8zB bqQFHi _ۧ{Qz!#Ư τKg1hҶ:UŶ)*KwRHC⿢( endstream endobj 260 0 obj << /Length 1413 /Filter /FlateDecode >> stream xXo6_a)+5e 8Űu(hNɒ!Mڿ~w$%K";Cx}R&oOKO,̖y$ =l2K'9ٯGPAfH?>r<xwEH4'jq/{ǞO/YW'.I|dbQYqoV?BL]_^rb]tucH�e>I( BҐ :Msp\\w\_a3^2̷WR=/ʪE][']SN6mXz$[ŃBj@$0Ґ?$Ayh%�9Ihm~mK}3< 6wR�\վxm5G}w2eQʙߓ3 9\Bn@=O}ռ>b,|Q,$v;!.n{y5sYBգp>nǎBԞO]xN*Y3l1;y4O8n VV/Da&siFh0Ik�Y Dl =SiYuA^)rVr[sDƶX@N_g ( 610 _xL<4p5ɖFcVJLOTD,i+(9;[< +G!Z,rʅ6!3&M03n7U�X|P^R'*!aCR` <} (_-nh 75UgC@=]+Y25)Rx{g[?xnbơqֹTҰw^g`)& aӰKhpV\ڀM<W\[\ȋvzv-Mr%TlrӲp[7hr-$phՖFu<j�DIhjffݹ ]!fI4|t$ QGF!gP sDo:XSбnG?l)ӵ$* ) lX!k$yۏv:Pok <hɭ3_O6xAL D؜ЈkZ`FXQ$hހA6^ ̦l-(ռٴNG"yWRmQ }Rbټ1L$p#ֹ}a>Ɵ*)QHY)/ $X YUeUz> pp/n ԛy2Qr\fo� M=/E/S8=&Bj!P<fNap�ЏL(xzΧ c!+rBhSގ)K<KEGx<X/fG(h endstream endobj 271 0 obj << /Length 2363 /Filter /FlateDecode >> stream xڝX[sJ~ϯP:6qup&':r 4*pFRl-¨MGVoӳzW-^{^o"&mY^Xw"W2t?GC~ D8 Msb{mp:!hfz{;pmKƑ>eue)Y[}ThPUy,E m_{e`;Vv>_u Ÿ8<l<7$~^\>_.:- JV? ;ͻ:-bqY1wOeh|$Lx<6V[^zTk< Q>wb-\i¶̲]*3W~:f$e,U$U g jSecd÷Ph`\.qxb6,L`T&Xߪ�!'f)R>cUܚ]\O.s?v"Zɸ1|rŅ 4RB|# ^P&~1@U 7X3a ,(Ʌ%qrnY:5\4>FL&MbpfQA`W⋛~w7 yUdc2KЊBz kȊ8jYJkޭH 8~Q*Z&t�:4'XP֯o=&<튲LP(TTn93UĽ~>JF Nc؝Ҷ͇3,ReQ?^maq_B] ar~7}?lv[OTN0Rg˨9J^h s=:88sPveAʅ?MѯU9[{Auۓvv@x i>t#BauwR9N+5 V38p/VLd uཛ]=\ӻ}3pdcRҠ?>1ۇL#N;]k;:ݐ0`?*i &D,O:&\ A_E=*=3:p~vU Y@MJjJnIXZG޵~+]][C%7zFȢ )&J`M=%STbʨj&w b34BNJ-" 0{J;8];[%t"‰aX'<qt\a$2!:hǁzƺ!8qaE򹒼-QvuHpeRRjZ0n7-q }[~jY�)(Y`d!#OLOq<s :JTdVE]9q}Al r\ 8Xhm\W8[?,%\`!҅yÂ^:>{IIE~;!m,z& XJzCl7e$TfخKT\ !^0u@-[1&22e9n$94dU5F$$.�kGSK6 q`^ҋF]C[I/E%ʦ(bZ�W!@8!<}ź":Q_yu :"?X=իޟQ8Zւ dUXQ GֵpuuJ2=GX5nl!Gp&*:}0 IDN/sBPy>-F�g1|P2oxV|RU-%F, hü)q38~a0z꿟5W&Mo˶C$ɟF(Cqi SJMBd80ypĒw}nr50ۢNcȪ9]AЗ$')*&7}̗ՊɄ3 yK o Zpqh וpdhkXG6!M0(6<몹U9.1,uIu3ła.mUFAFUWPK4l =X׮9X|YiH|{=Q76ɥKLi2ßBF"\ =@ ԗ0ev $Jؿ|<ىYwSNי|1z-CGk}�!2s0ƯQ1=ޛgD}s٤RlH~<pǤPa3I\p|᯹oY_o'Egm>LOH7lWH%tHqr.^ {� endstream endobj 283 0 obj << /Length 898 /Filter /FlateDecode >> stream xڵVo0_aVLeҀ &$1U㶁.u8&mCテ vҳD0mL�#`A8|EǷJMye#)<HV!cBwjbJndš>ݒl!lJwKJ!"p!48O$$6K |c\h"HjX <F^FR y?s~<:[I_} &\u<L u4l #6s&x)_)UD.4ep϶2&_k}1Z Q xM`yc %Ng.5!66]ΩlNcy<2jk)-@MMKi</v7c-z2r}dYKCaۧ{_N'=$9!QhֻA VrD!+f\tZ9zbb)(pl~5mj-5Cw4#N0`)-'dUrz B'cin04,"YD6Gk1"5C :BP?=sya؟X۠` WyуϞ-l3FU;NFvt:`w" +h |UvU':tIjhVJnx>JnKR]}ddEir)B '50#5M#{@ {I3 ϨKf8IsQ)! POMNR W-=;(!.MӄHf.Q+ӲbyFfUjaim*vSvvEEeji.P_zU4UJA  W endstream endobj 296 0 obj << /Length 808 /Filter /FlateDecode >> stream xVn0+)$ IZ (6)SAH-Z"ɍۯHeU\q.ffMqp99G h<Alsy.8Dw"WE 3eޏoF'.\j[Q Hsx80%c3Să{BxSm#N) 9<k�@ v9E:}�ZѵC: \i9ĐI'DmlC!{DŽ�vOG\,_ȣҤh##GUbX_ 9U9SQݜ-F<5-#WP0 ΄!u:o .rcUR;ܢW jɅs0 J: ʴYm=D(ǎоޡYe%&4)ekQ;9BPu6v&O5;z%ٗ*]޶ƃ}Jͥ=JtGvKI ~N #'lȎ{vrb,(*èpyf2/[j׭X)PKq=Xq0.^f .} q$]"+r.̞j*WS0Ci\,$˧J(id*jdk&T�ν[;` ˞k>J7뷿 Eg fp(qzA &'FyLE,gYiDžSW]L+P{Q(apVh4!R(˜s%țPMv@;- endstream endobj 194 0 obj << /Type /ObjStm /N 100 /First 878 /Length 1833 /Filter /FlateDecode >> stream xY]O[9}ϯckόD[[iWvU5$( jKpfW�=w|</;>OdDbE3_FĨm6S) .9o<2C@b '#=)0:RXGHyV:"$} A)!I K�ǀ " >fB'1cr t ā ;:A!ٰw:RQ#:dvGBHWj8(+#D91 tr(kN!o8cBs+ $-S}h%J )z#sFg�F"{�%QTɅ*CЙ Vi'T2,($]v'$pMab!\XI(9ٙ袪'BYi1`"&d@8{Ew9gt AuP /(e|kSHjXsQ=1Z>5ǰ vr��:IG$5q造&05o͑90oaJVht{j-ЂCsOsk}XU[> WhO''920>7?}1AyL}Q?5rz2:8_O#<` \1[ %{ڨ4\iE[VU--Z^ҶwVk/Ͽ _{t0m]ȷ(azڂ0 CgZɇ޽8<GrddzN3@ɺ1'Y48 .=8lw8` W}f5H *iO޲o 2Ye#Qy.Vc%Beͮ:`0̛YL%Ȱb W<!g[blZF^@[AN'1 la[LrN%6Vl|v)Kv Lo%l (c,JG3CàbܔoOe񠵐+3?*+(? zM㔺LHRznvZGo{ LG<uH529+m 9c\NG;;ghŧwݏJb=TGpL;L(!"Z#˩ 4RNMaJ R`5~TF 3P0SQ/@`A]aG{*D$'*,Zq '"`Sp: 8j?"%%Oux?'%ՇHSa]d u`N $wtAt5-jձ;1^ۻvQO-49r xoQFҌZ2NA7fow;'xN^.N_}j>?47\3]uB"8zBWsxN՛M%VQqؘ@tO9?ܭ{r*ĀJ:VZZehOކ &Xjե7cÒonٷj5t{ILl` )>5zf=fn $V|H{!.<pEYyw3*Ѥ`6JX+X3 ze*eBM:(J]E]+_Se؛-cAPK٦uwkpvOTI/+9פּX Eo^ם ׂ pwKk< endstream endobj 313 0 obj << /Length 1445 /Filter /FlateDecode >> stream xW[o6~҇Dh tk :`k]X[DdQ$;H6eGqiO<//9C0F~9qQ{΢p>M }Y_'8GmKA6<:bmBa{ "N|~qG8 Aq]9'hU81 m~b릇҄t)\/ӏkjע#~\aX=/g#xy[6dNIۻEq/% mdhfb)m DMVoiŚjl[ut<<)-%߲zMXt<j) $(悵02]9xzqҬ�bO_/w?X;?I.ȩ&;i$db B^G ^PT/gaw/[H|&Q=I88E8"Ti)oh.ʙNof$, wex!RFxG0lEL%tC| 1!Bt|FV7='zPf%V({wx_@ 0Eq$N% NP\<˙N3s9+zet}d?뀇y+J)Gk<ͪq:s=$ܙn )Yz<mB0r}fBhu5]((9EVҤ8oZӔ:3ŐfK 0Fp!qw)x^WQ{H�EjYjݝ ?fEQJJ В>ԖlmI)|9Y1Z :G/2۬`!}elx�qp>\{.OO#<]`=5*(6;#HegeMAtВ 塛F|jUQ G';a]J)- r' A`>MR˳r$no,T6oRKE^2|_S1HZ3YL>+8@5,9?'Jp,v9z=<F,I]tje:WC:py(\O.tE| y Tu6?aB&~k`w_lr&窝c ؍tFVViIϬ5A,+ۈc\bm<|w8ߙi-Dx>4l)kWs󪼆=WNW= E^z7~k_4E2R `r60Gb#z~J={<{Ud<zЙOlA@}Í+t`0GL�2Y)�u&a%�`ASC%F_j1U? i endstream endobj 328 0 obj << /Length 1100 /Filter /FlateDecode >> stream xWr6}W-LNr&}pug*OIơIlﻸ"eXӤ} {.B8 pvzqvyDR71.Hb$ yqJzB"-UyMqLPSd1/8 (EAV->~A){ 8].~eS#Iah$0g6Sd�V MƎck I~2aGKy%E„겶틦<�%$(Ɂp[fM:k^kH:/Un' MR;ԻZn6v,1-wEM|)?iyѪoگK$Imvmvu6h++¨ҿB\rIG 2uߕ&&HHb~e!Z<',-+';\~x>Duj7J@*LK1HÝL+e ףM2A<ml%GG�)bXzp49%(Kk]e*G_E'HbcEG^}߾@P}[wWZf) :F>StN@H¤U!$]Z>4f~�:Ƙ>ijܚ6mӬׂf7#YfeǦ?M d]tq]IkeS 1f`' i<ũ,0yr" LsWg۟1M 9sk<j~WnL>.bģTM^hm1t (H"tfLW!2" 0ƅ&w־*9ƙM+{Q,EfTJ2DWN 8%+sذW}|p:G۴{2GQ:b=DYlN]޶^op~\_V;fQ>ܲ!ոjN(S <[}BU I+ʂ0 .goMfuºɕ3S>6NXyQ?k9G^Y endstream endobj 345 0 obj << /Length 1603 /Filter /FlateDecode >> stream xڵXَ6}0܇)Q` m�Š/Im%W,E(slM Dw9܅x̛}jf JB63yYzdv>9,| %(BI f>6M%<m{.4.Ğ2PԆV}<4,<ZԹ^$T=t2_`uSV:[ ԹV~g#n[J"'^Ufz0g@I�E)*?>zh^*@ R% E<cOc H\1dB5oNO\0#jNԋDF $q�O9se*{V4L~*YGDID ?B<b␮_"`)K�%ZFL F9܂-!�WG_7�abvD-2{UjPa46Ea1X b6 9i7JV$24[I6X簢0]BQ3esv…XcEh?@rNi )Jl[8 nkHד'(97EGsԃ.Aij_|/r-SMٱ 1JJm.gQjk0!jhhDF 0ֻJ ˍDtH>T(P՟8' c%yF`%{RŚ*4z<& Q=M 6T%<3Kb:&d*TK+^-pw5a8к8Phm֗eIrrSs0H}.CjA+$qKxT8G-9 0 ㌱h|Զ41Fs'Y 9Ry>֧K>]QFG -H[ 퇕w~vXA;&=)[W=+f_!"۪K쵾&Ccī>IG� ` Cࢅ7ϳzڠ@8n_U'A@XE!�,E%w9cP4Grz4 rγ7A>=@k\Tq(EK(YmГ1~:t U/`2N! (c%RCL`}ZbVr1N+i]~aux(L,r-Kuz~@ S;r<EβV&Ζzt<pmmNSl|4>кχn_MFBWsǴ T+ Jȷͼs\*S͖!]1lF乙Ȣ>>/_lY+,8?pz䮻]<mŷOjFE:-kFUiDL#*Yys$d1%:9T$D xМuQˀz\C)8^OL--l|~NUF/*ceFc;Fk ̛r~ >V"طy'Kg cz)H=, bλi� endstream endobj 351 0 obj << /Length 1003 /Filter /FlateDecode >> stream xڽV]8}ϯ`R7mgVCݦOj'A%ҙ^c@'scs/F[=1b\zH0RI|^e8&( [I a2/XME/ih?%WMS՟i@ؿ^,Y: a^zpuX__n+m1@ hX'PnMhv;#� {(93Rx # y <>>jq>ڃ<=ɉ'CgB(HoʢnCK*`ӢL-Jb@-[al%NmVI훬,9mkDHF/C%bXDkѓ�ƀ 1 EbU@9"\ٳcՖ7o!_1%f\اuǮ#>+,׿ݍM1�(qv\?/Z"B ;5e)}UMkfrnT',OM:z50<FVU*itզ&&bDfn ,mTDWU_>7]O.˿*`u@.P#%o܆1<{{D*=ݺnU ◅ \{a qp^5{USynD%8<J.6v`1Yhl0 @;;+]A$~cH}L{U9c21ھ31ÖIcS|/ΠXE{$X"�=Ȟ0Mf@:{ȳb3R&}إ#Z,WsLu>pB1Tԯ(1>Fsu2A]ڕzlUG hvem'i⮪uҎ \<\Z*E{e-Z},0*BNυu]87\:>}cwf9꟏7Ru=X endstream endobj 373 0 obj << /Length 1522 /Filter /FlateDecode >> stream xڥXs6_\_L,K|II.v1KmKܿ`Ĺ~vWZkZ?~-\ϊI8u+ (]Ǻάy럗Wސ="Xny  ZS 'D>{Y-Ӈ3XD84F$񩝕R{_2fY{^Iސ#kF =GN7u5g>V;Fވ<Ӝ#G"ġESٰEhk Vۻ~5oںдOԧw;MJ)Q@cF|9 QRFk0Fq=-Q;|9J;/6oDO˔�0rؕXY}̥S >QԲ/"lkSyjt^a<_% D?ЃL/ xڨxsǷb75GZ*yHCˬM;�m&Hdh^~8 <26l!Guc9ȻKU\?p#/"*NtjtD^v L*hݷI.02iuLAV!Ki ub[F'@SSZaE|BEEcgʠ3MXӁO~We9# 7Z -QJ ل $ vυ>#0Շ.Lb+w< яIwsm J OCsq}J+אb*IWaě'C@ASJ4ڮ7FFa 9BE`.ZકX'W` Q%S0pYJtע0٩T8&;HsԥYRW)|>r^aU(uDN˶h4Iw*yfRo?4$=�=&.pbaY84 qa763k;`v'okmvyx^�(ݜ)3m|Vԭ VzSG�9zEbO)'͕̕c{( Rʺ[§>_g͓3`|sC8Ϋ^K.Hu nx2Ѡ!7Ў䓇onP@dF7ڛʆB%.x7fj q **_ˎx#eTmT*�Oќ ~اqEc@tBvϗ!^-zM,ּq6ld<WifWqg1(Ey=R@ӏ_>!o,MF6qT)I}ٗOJ$VC'WqNgzv?cjqCB#J[je GփbZ9[g< Y tt΁9- mjEyI vIo;o #"w\Ph_3_ٓŠ?e槏 !L]'?- endstream endobj 383 0 obj << /Length 1039 /Filter /FlateDecode >> stream xڵV[o6~dC.ֽ k54b"K\ -||<xuzq$ Boeqx<TcdJT՗wth0AQ ڄn[GvD;cs"x^y HD(kj Bā v+?,λÜ0mS(ywH])(�Cg!n 9}_ >ct�'%<14l[ygw5nڦQ7P&f V{}(s +(ۦm)Ż#=xZ|"I蝕QXş=f 2q"ƾQq<쉣b@BBr6Od0(czM:{0 ꭐY[TԳl<k1c#i "|y5y#T[hNkxټj[ԳBؠ^ä$Uj^ GDr8%yiD'p;F4fSh"OP~SP e@f][窐7s>Y"SmX6Ny}a]D\7 &(d>.VIPY` חOoA�'#`mOiO3/nhEW()#(OdWjMΪqz@|;.zݚ;n#AUDM67E݁litieި<Va-N�AIݦ$DBoBf۱ٛE-:&5/Y鸻ᔹ=Fu\suZ?- {t*aƄ).m(Q^*ӎ0+UH6r|8 L3aPL7erBJa';JLy|~<œQM?E1LGl*:kwOm~t|bnGb>AfHoC>DcsOPyv endstream endobj 401 0 obj << /Length 1761 /Filter /FlateDecode >> stream xڵX{o6ߟBM"ZmV kC_ԭE[d#Nx"Jb+B=~e, uK4َ]ܲxY̵%)fgN 'uz,'q hHzjyw~&l#�fQF&,d3ӵI_4-(Ok B7u!<raw<0gItB:|AK,ZDeWiy积<kG֪7v˶6+<z;F8KIc`jr%%!񮒴(eKR.vں(E7.Z&D@oG<Hn {2kё}: 6~}xs.H~ف=GN_<}pA<;91nO|WCeUk(q`hV~c\Yt6kk?'|p4G#`f4ۄF/d]ջn,7ϖ تk sǝ%Z=x7\j2m5`, xq63kM"ơ*iŌm㜾כ$9/g?Už2{HwuBVGwY-t=v;46MC6W%lk8Pe%&+"G溔RL-~4sݩEEd\iG/{S4zӝ5j)uWJ\.qyG MKYIA{N䘶m91؆jmuڌ{Nq'/)E>E[ImI4+Y.]1B1F',c)1v\oZ6:X.-,EeZBw� sO ڷ~ E3% be GsOH>)8z}G)?侗DJO `L3 ,{ѭ]/!UC[ׇ`u=Sh�%$l�|';fc/VFqMQL KՐrzPLɮ?ӜkK5Vَ5`r9fUuI3EqwxoXcYhݟbot^�=ws<e#|xWh`jV�(t&yͦ&"Ti\iZY$͢yq̈́,0ʥ.)<vNڡ;C /ږ\O ^LT2z۴%^HkwEH�(]*B$1<$r$+B()P{BdG[p(W A(* x16xCAZAQ�F +ߚX, `¾.χt=wvX$pUUNEf7 tU0'/a7jD$�w/ƀMdR5:RՕkO'bBqZUr-:"]oJBƒ_�9-92S`(Γ`-\vG- L5 {#xڌAlxuYg+%�pmݔFMi p01-|/sܨA*9DCBF�$˅J0U d ~msiz6yOhSʍp'jx.\I/ͤifF/ h endstream endobj 309 0 obj << /Type /ObjStm /N 100 /First 876 /Length 1523 /Filter /FlateDecode >> stream xY]O\7}_a/C}xƎV)mV l|dJH-\߹3K Gg" W krQIӠ:ai[qiR쾸yuUqO@DHl lVv Zf@` )lp� - 1`ي ) R6` 1dX Z b� aGGQ"{ #`5ͬ_Q.Ob* ]!)ƽ$9،gx TLbK#,3 Unr5<$B" 4T : zj%[&Hc 1~̱[<W'7)>ʔL@YDㄽjqq5 i&M12HXHfb�rRζئ!,åb`PO(Da$zB:Hx\1Lj2}OG" {+m{ {ܦ~Om>yd<<ރ7]a>si8 Bpzm'l̞P}h]ތ>݅7Ѡ[d>C8Vh6=9ۋ~~ręG# D_CSd2>%-v  q:t?uu vV` \=WlbL>ۤ3'N͡pW6tmum'g]h<`~4Ƈ ~4ٛN>x~g§~77䆠j':{%JRT^Şc',p>^c% plâ2 RmRr62T|AZ KXp*Hst.b?ʼh|hՌڅls<<4G_Єh+ 5aDZtϒO5>WKioK)OCN�Z zBerݏ7S y~Q OfO-u|i.3B)ѣefGuR3= ?'IsJLl4Hɂ=%/b/r!> O*U ]K]$ѫ.v.b[{][-w;}B[iͩ 1{\ز˃%6b@+zX]BrZ唧}[YA}8/")A|HF.g.d#/J]ZozYfP΂xS D%�kөkH˷m)\O )<h �o}c%Jķh~0ݟ={u>ޝ>yj%,6kiԜj]8%/`(Nm$J`9›,sz_W=U4 \4D(=@uE9j9ۨ55^~-5d'b endstream endobj 417 0 obj << /Length 1454 /Filter /FlateDecode >> stream xڝXKo6Wɡ2[N]-Yl{-ElTw(ROSN <^|}ww}_쒅1r\y/yc?DYgJBA*v+,WXm鄎`6@wHRПa;TUcF$Q=/D}(,%{TEr)otM(@�-Muݑ2ٴ,<i8yYj۷I?=< cQ&Fvn8l٨dQPW.b1%>VJ2_A3x|$V1ʥ]^kY\V-d>2z` mKϗyXZMȒxn�D^g<-v:#|*K,$!/jNK3&I<:D[ rG3mAWо|l B4�V`ǨbN*Q=qEE䀵 S&Zq}<]ڞ<Bڈ%Z G\URlԐfPhȇ;0ZzLcSm#! E{K$jƗq) kF4.賦m8t߈oPaQR0.UZ>z̩@ä.$YB@#@j Xń|_cO/Q8K|s7�wS>+@~I(nJy]m7!->^iI^nk%r?621cCIZjr"&اIb%A 7Gx 0g*-zQJ Z5È1\n&H }kN+Sg,�!3HܧmjTOyJmA\G?m)QMFseq Jܢͪ"4bR*LE Nԙj<] 1TJ1*0++0R~^<p)=15d]巓f�ld3,e`*Dpxޘ<UY%%rh 5jzxZpqY\~j^lˇŰdbW4A܀ɧ$6PM4j |! 1chqpp T#7U?:W/yh3=s-3QeB?H^uw dm#/ r�nuJ.jҢ,; ƒlh]TU6i1m79J$} /fpRL/DvhM΄RE`w**9/VbD1ͯ-' g`;@vsq@ jb^mjO7L6+V)SsϡPWn:Kdcǥs!a'>m endstream endobj 428 0 obj << /Length 1329 /Filter /FlateDecode >> stream xڵWYo6~IbHۗ"% K^I)$m�!M $~]޲KQ[<1baFQo{|/o1%cE,>qSU2uȪSfz}b<<gkҍ6;^-m!aHs#2Sl-E*!i{)ߘNks]2 FRI!ѯM.Ό?6kmWԕcoNRpoIRlKAmӁal)"g+rS,`n(-/9Ǡ`k͒݋Fdl2Cbͧ _ҟf}N:G[ٝRЍR# }=JI'.cycb36X\m<8̭U:sL!#_E!7ۇp_f0P5a85؊i5=k|<&k^N(&)m׬e)JpsJC( =PRP2~I|Gm "p)*յmYdEWٗ( 6Z_ΖX:10J]ʹ*2HGaKq*h w)J( ~B2J [ yi�ת(liL-I.�NeE1Jd>n>rD*7bS)&6(g;T�]ˀbI8 RuEP8f/6MT VYvGYQiu:1YW1чhת=;p̝M`D*?_,T$bM)Q,Nu^-ڡ'NT>�ܖ:kMu44U~4?9eM99mlKٞ?$, P*;3&4RwrwWׄKy7O`\Ny:18C dDkD=]ev*&~CZeJ?ԥ!'pzcGH鄓7žqlT'GmݶŲ<'0[u7^18o,$ Ms,oGeqBQBB5 CUIוB0QQk~ <5¯u%o4|ꫂmRg%27Mj4͢j;HL aoa.Vd6(\'տ̬jbl]Goƍ++l~JM:b# endstream endobj 441 0 obj << /Length 1514 /Filter /FlateDecode >> stream xڭXY6~_!Cg>ll"E) $A*˴V!%.$j4|sP8$!aNR,V~W|.٧/[1)#Q 4K5W x=Hp&Ѯ[>@I,ϫ*vl?Ҁɺɫr#5eU܌/ng,PqAz:4J9$A|.-:ymE>2MϪȖ:o D#Jj;99g !^:  nFG9Qg:AQH[D.rw3#Pvq]Zn"ridgTy, ,PagnM4kQz zk+|vK͞QJӮh >VBF$73`M"] %,j5 ,H)+ETPߘڌmv>7պ%Uo]1/%<hFgQ?\$!je8a i<f`P9mX3/Y�Pe.WJeShuqvlsU7mdkK$pr}k|ߺl6M)@igR 'Ò{[ D&* u+ ǀt''<-R+LJl-Eit{0PnuGLe޼}fB/4dp#VQo` C^`ㆰ4U*XtWHZ@}= k([RTYB~A(_xxX�r:,#*j*qB"YgA7Md܇IL\VD�C])Ig;5 62 yj| ?r!^7C5%PRN8<n&!0:{ Tdfj՗+ o$3]}D|HD;ͺs|HW(wW?9P FI3G0'?H@G8�3[Syfp@" Q<@p!&&MTMV4qmAXÚ3Z'^ޱ )"ݥm>4+/�ͱLF!o i3tsTs=6䃞MVlikRLwG#wg BRZ,�jZ_3V|*do"rl>C3LVA�臏GˍvMC: $}:ܰMՄ hX14,-:!T EZwepby+F5J_m]Q<K`W~Zme7 ԋ+U ;⬊hw\Qb̹KL6a;lG`Fe?Zq)7-@.?B\^WEQAc (|M^BU'42|R 詓[ͪ#lƗn/O ?p;i endstream endobj 453 0 obj << /Length 1049 /Filter /FlateDecode >> stream xڭVˎ6+gQ$E�S4)E"nHh[d9ח%eіNە(%o_;y JBz˵G0F> ((̼OXDimb+^[ɡ=H? ^؛1>Ng4tk6oSLDT)oưR گUP9x)䞧̝*QY 7[LOḣ\ /'G7Mawy0{R!bAϼBwNB!Ȍ=O3xւg+E8MC0$Աz11QI0J uU5,OfUJ ʼmuU*/;?,Z/BP ;3X\!̐&kNތN%$7P_[jZۅNLuy3�D ս݉0)ᱩτTtD i~)]M�w.y}hAu{*Zj] )q[F5/FdoZ P=ɠHĽ�t9vH`>&vA (^`|Py賖n"SYҜwM%ݪ U,g.[񢽰X[rMmvZ=ess']r3SO/-G>c/S?U'Ԛ#EL84h(dc_)tLQ{|lq(x_SLҙ=b\&ďGHQin_L04T})qXyÝqs�kn R˨G;Ck P͠JXA+vFx.rA+sDhh$u·u73:(\EYx#c+UGMGԆar/| WGމ_7Inxu( endstream endobj 462 0 obj << /Length 1152 /Filter /FlateDecode >> stream xڵWK6Wۋ ĴHTllEzh ZmJ>;P~<>~CGG bK&ңOx PDpSanU|1}$UdԨ|g~vø G(OYhm/"UyûTb6K VY09>EIvpQOWFW(MmYi(zvyBmtUqXPHTqE BI}w˴=fNTXE}k=a!~ӾGJ d3RyVs*ps诮OG!sC '$Ab2GEG 9*wP&\]`MZdL, ,;"b M Tb>(NiDC|4vzQ_% 94r_}v639.wMwD B#nT-L/Ѧa[6Qٵ<0q3:MJdECu859`PHU\>d7Lf 9qUe2gxO�>z(߬"ѻ=XV=L[S '1|߀GZVJ,K)=i/(8yIZfe S>v9ű*Z2_\.BUp()tN+y傑@/r.hY\mMDgf6Մc`pYQ1wŁ'-q[huHAƠ3P44EDͭUybp:3C0,βK*R# CB=pYT8#Cb$8ul/ql9!JD܅G%[ЦlzM�w;ZE6PKv"Z?"Rkn֙�: c`]\ uӾjڌz<!'rG79%w +{Y^>͓XSi}0xgc~dՄ MLk'RRnQ׃? ,=yݟY$9)Gm ,+m' ~X�}dm�';can>|8 t$= endstream endobj 480 0 obj << /Length 1528 /Filter /FlateDecode >> stream xڥX[o6~RY"uyC5ņt"Ӷ6YDnwCɒ ;HE MGog.%$ yݮ<F) DE!%2s>tKȘP۶UE2g  Aܢ=!QߪуKgb`DI(#m,t$|%Uf^kY-HѪ!#=uL:e^=^g^S#Nje"V-͒iݜS(;٦wiҭ@%r.(~ۗ4LwBju.1Hg]"'IYUbX;Fa ǔDSt .ENZ!Z45/b@x5\F%aI뫛7r!.0l;:EaBa\\8W 1Vuun^Υ5e×&gS?!:--V՜K0nC4&]L I &/#""s5U:7v*骱(MmYF{=6&w(J,YCZ7Hx&ވ#B`  M &qU }y:NKen 0 Iœi.mT.ăr7վppmea`|&< İ,6Aa%#8_ (s9PA\NWE`Vu۶π%R6v_: ](<e_~(/\E3ja,ZeY5HΤ_bqUyydrʰFž82VjE NCPժ%sE}D`3~VMӓxk'&GJ./RnI aӮKQ~-0>RIM$LHu5ߙct*DB$^}D%|�jnz8aRnf'<ԜsD㭤ӕwoW.-,�|MΘx&O1'`bbfk3PNk@7 !%^$h@z̒r[Ě:ǰ}9uC~5*zWq׫A:78$IOٹt՞$.μ`by7LNMv0n8$HM!H|,uXIΛ_]MM ]@arEǴé*Hȁ{S8H=kP( +DF|ZZ53nbO^.nۛ4XA1TtR߳N-)fn00'p LȂ{zg!a�+oh+XxDblD^H""(;*:DVz_1ZD}xA.]+ F8,a}%LK28m8-I>TŰRI88?` endstream endobj 494 0 obj << /Length 1022 /Filter /FlateDecode >> stream xڵVێ6}WR h^DJ\dA6޾Bi,/r$f"9s8gxf(m=2q1GTP-6Hx3-k<^ևl%ߦaPed9`z3i׬c?8^y 8D X$AG+W*Nc!v #ѰR:^A1g+^ͲqчCr>[ ej>.c(b`M]?DJPJbobc0otFl(TY:޽,pj�w֓?N#g['>bo XxtE1ν?޸*@t"" 4!՞l8 P&{ yNڏ\P)E+(j9Qx,U*(HS)yqt`v\y`p+ud k;UTrޥ2+VnʪF &(Il+?3\ uh(wuuJ]ltmEs /;jcBO)p:`f}]>kPfmt8?п[~iA@SyRZ-%<- qҫjWM[{狚`}!s c)J2unCin9Bw/:1:3iV,}}qomU3OR!N؞OvbQ`?hb&P6vZ֝6~=#u*�8@ k,1ǭlvf;م\t2OJi~:dW3f ;GGKhp|� U5P)*6(Mu9R)/XD(qgf0d)Aa)=TJ? QL*lJ- =' 8(꽑mm(b4 ~w2/AK0. endstream endobj 413 0 obj << /Type /ObjStm /N 100 /First 870 /Length 1564 /Filter /FlateDecode >> stream xXMo7W%9˙8IhNF)d }r,njmm7 .⡮,9fG1ۼ:ΘSpB9I6g0Z]Qr]gq%RWgr5c]XsE"eHà2z+1 VGU)$8pE !pxVLm0Am$cPH$BpU(gͶo9@MU�b `W%T4x5C@fV l*c`Ga(<@o%1P(8d I(!(V($XJE+5gp81١L6mN0^C1H4O‹v{q2|Y7 dEfpvbe�_fPULVcê`v`Ud"t*9Us`a ~خ \%5Yxju$W0W2$i/#0)(Yf&@g6V`I8Qm?@Z=98={e0_HqM`.qMXR%m(ޟVn<vݾMd~Rb^<D&#ʻWt\^O?0?&念lVKgIr~8.<ڋ~O?#ۚV@)p Xm d+ {m&m^YgtѯGO̦lY#j)"!>XTKzoa<9x;_ ?[jq᩹ipfHzguvd9qCM)sjԌ0s iYԀFe&s8=9ކSI(R.jGE@FAFa񔨁JC=2L[ =Yb6e~:<DW"#mZNW׶mFHb?Cf�= 6pHZ&UڰۼuCm` >Szt;�S*^r#QdR}cQdGQ:+/mQ 8&葔sD:qy|vd'gՇ񿜿]]wz]d~z>{M $/&﯄OoYwFNF<$oSǍ7VО61G]&0. >0qGvhKli`FUiu,4rvnpB>b{vBwr8aJ5'wm4CP@960= LO+_K၌Kθ!D*^6*!i# Mh.Jxj 0%Hr6UyG7f 7b3y}>n>e&؍"nl߰]l6훱G2{mTX-PGtr_XmWsmgCtXm۾9=t5!>F0HVny[? LIG-}A!]㍐r[C^dXWѿbv endstream endobj 508 0 obj << /Length 1359 /Filter /FlateDecode >> stream xW[o6~Rhd dXmhum1hm&~/MGNݧ!H 9ُ6d^ҘzQboc[{[vHbh$łDT3lu-R[owe[z($^@R8}4 ~jWFϛLk7_p[Sy/:aHȑ2Y`$F ::W:ۮݠҬ}3[DY F)Jq>kK (:ao^μϚ, 3-4gR^vE5?ռH~69Eb1 븀F!bQ237)U9`5G~.6*C\__Lh8R9IPEFP唪Q6F@LÐhtM/y.7_N;i� \.#gե譂NElJ{|&؎}}Q~.~4LE,Q! Bk?0F1G߬ʧFS$#K@aXigmjaMzɚmQuMܥ׿&�4F(w* l DR(]PM+jss[_;d9!K454oxBJ<[kZqƚ@{.N[ S_˻liʯ e,Zhvߐ*Y{iR%L2/]XH/ 3|+fFiJ`5/ˑ岝vʈ]?^]" 3:= WKFbL= @bX>!!8%aLin;BJ )t+V!9\f$v"r8CPFNC7nd3#dq|b AQj#r‹4jcpWLVzog|zFs @X=R<"0R�od t`;aIjb8<v#ݴ*wmpb�e5'g]>, |sT!i<&M' $TeV-34 +!ag.Λݝ}Oia(|ݐ8:T 0z]߂0+ dz+Br|[]nmi1r 7N Ʃ_x'z!OTdkm}˧#}=]ϺŅ[Sԑ}Cz6?Ed?߼$)bd_OgڕЅ(cB{HU%"Vv'﯅7N%@ڿoOН|J$9 WW3`4@, endstream endobj 524 0 obj << /Length 960 /Filter /FlateDecode >> stream xڽWm8ίp؎$EݻVznJ'V./m+<kg34C}98�I4"JvD$X ",RG[ ŞJE&JTA׭+>9r D-s%/-a g/fU= Wp4W2R66`<gIjg9TP}Jp ZqsȓyDJy޽ͥLժPQ NNO4z 捹q6WrSuψ>sU`<^mw7ǀ6*NljҖJr?LBj=^:14ˍ�pRzB͕�ua ѓLb8Xf�B<5ri+(KP]@[l4,hɳ ` �To _ь3gW].8,Z wM܌:w(\H6( ,MG" )]I?GJYSQ�.9Eau$A|j^*_)7)s+h3M%"գO8N$#6Z5= n&y,,mm{l>^_q5R4mI܊]WL]>BhT.{tgiqzH9r޽ѨLOB06&@Q6)}W%ưMRZ5/ 7\m#4ˆUYj{ף8 珏@(nUCV/x0d/e&)�ed+^fOL:^Va01)_D+uR IS[\I* D&*T׸Wx}ϐZ灕'cn;Q2'N0$�e$K{;Rk|H endstream endobj 537 0 obj << /Length 787 /Filter /FlateDecode >> stream xڭU[o0~WblLLK'Mݤi5"-@Nش6|w>CsaB~jo p`N&x~`45o-wOߕGN#WEWYJ9~괺奲pcXho82mh%KZфJ6"Kx\+V,RAMU*Q܍ Q藱釃OV$~MAsj}Sr`D(�cQ�y' Ov4_X}BO+&҈X(*)[ tU.l@h:jMg!b3<(IgZ #q'ALG4lƌVJbb;`t:/K'VƘL_Dh&1!$7n݈榏}•ye|j32}|$@$q8< 1#"F=Po/4R %3!D"Q ^pIyVyb/L69+\Ѕ-$+j> �l"k20D?<tDWbq0I,n#@ K}ҒQJy'`Aľrp|X/`!) .=^}_WAu/u=W}k|q59u(i0\햜뷮i,ʺs gSGE{!Ip,1=@pD/zwrE_9<q1 -UPm =*k2Oγn+CL(_v�tUpZ[ endstream endobj 630 0 obj << /Length 1592 /Filter /FlateDecode >> stream x[[6~_Vj<`Ԫj_*U[EL$"Lv@X 3V3Zw9xmkk;移GDZbAv-#˧‟~GX 0["6XGx\{zc?@4\; w誐0VG:H6=u<+�B(.dM & ص0`^0 2s�f"Ca &8,LbⅅBJ9#Y|D xk(~LKB|⸞J9:Hq|Х(+=ƒWN/$cR՗Uy_ ~hD:҇%썳ѕ/LFzx] XxWq/R$;3ēV <&P[@X\:`*T!Ω "Kr<3N5az:AoԟKۣF,}x<[n{҂2xi^xdA< mo!n، �Fibϳ]_ -%kb@$VZHywipF*e|�j7 P=0u$rYDӈ4yC!Zw]Skda.Ƚ2/g=g2qx#n"77(7C(G?E]&O?|;B\G~~Ӓ#ɶ\o j{tѥƼGA7wqi-074}AZ ^0] xJc/;ZTvζ#^ �K\ Oh~70 L۹Ĕ"A9#'>8]Z /v'xgm>b"8`DVg/C-2/}`Ms9`WQxHU 50 KFotwÓ#PXaUWޙFJm?Sgn͋4 nŦPZZW8qv BAq�F4C/3@!oiy{uּh!|A?54@72~nT: -ȂŬY׊0~dctg%fK9U;/8_TtMv{Us6.o[|XObrS ,Ж-vDmyjlfy;M\Yj~xvhm$uoS}(DoQK=�=g:2Uh//t4V4, .ksu͟k&毽wsa^k]H$3VzP6X69(3W1[QSt) x`=/uKqf4O,n*Oξ5x|֖ G?dX6eKs:4U,4< {!\F]hXcj c#gr-;suz_elY]2䛹m4I;�;Ociu {+k҂z5V%וl_f endstream endobj 505 0 obj << /Type /ObjStm /N 100 /First 880 /Length 2203 /Filter /FlateDecode >> stream xZKϯ1pXO`( �< ,v*p})-|vs*:GiE,Z+cB s+=޵)q^}~* ;eV9Z7LE�C 'Dh;#+=4Q <xQmiQCǂ1QS4�Ơ1g r/0G,L@5ix0*<!WRI遃bLS�?):b G *FMa$O蠵1<h< Aw^dWom`t]Tз. ,1voSD͸hڢHx[Xb&Ph98s0C]Cxњ[qZ܂U|л#&ϐ3a;:tAt֥7ZC.!T�}h!> #244 C6 A#Ml3hL9L7M{v'OvEʳog8]^}iZagKk E C z}byڪBgJ>-OS8 aO#2A)_"h <aH7ׯnEӲqM?ǫv0-|&BׇKZzͫo)D4a{T|^�D([ȿERh?`퟿7Wp^ Z^(nR;lڻ%f͊TT,r|^~q]?<U}}}uo  M\#Br0+o!0X eNzssQujXpr G;1kd+bA=Xz4E̡:m{(|5>'֋'_OLxъqD51B0XHA}wsY7WosԓYd_#c}\^bj,u G: t>gdUڙ<#E2Vve韹B|/^r # g7yĊyG,Y JJ-ҥ}j7..z?Ȫl%[ֲM<K<K<K<O<O<O<O<O<O<O<O<O<Ox(3m'^Ox#F7o$Hx#Fe1`Y L,l&Lx3f#-eJelGGGGGG)(((82iqN\}dVh0]m)W=Af7?˪XzBU@,$RatER B~'XQo#!Q!n PAlPB"Z;!9pC&[~5k]r}AClaKNay'\V IpQqW9^="B p!s&4:)R.<B9e+Z JYtH-N ڶ2H"E:>%_Wm4k;0ىY!=4 `T q4<ex8y\tR߈|/rB% [T8` HF L&󼣇jCVy3C] ɲM.8 HSCtTt!KD*肰R!O܆\-vu^NAS7^Q`\ ; $)t)˶4O:pll TʼnEMkUr-?3XTQ3/(".%'XjMX! 7.,68&0Qks۲ A7^6zh1fh7YƩHu:6'"H6@;AYZ7݂j\xГ h۩LV/*` KQԸ}*[Y3DVӚLH81&jY6ocK*mʉqh[1AQ-wЂƮ괕$L R[:+| ׎nÄE|D6wOTibס$nyCmQq*^m砸kԓ8#oVLD2q34Īx endstream endobj 652 0 obj << /Length 518 /Filter /FlateDecode >> stream xڽVMo@WHd'DS$XrvP׳b7km6(ͼ %m,W("w(hEA"'\_pkaH4o.?v^bapWys5MՒHڻ8p_m�cC Fk`f>`HuOW ^pI/ͨqX)E!03ThA+Z Eo<ZGiN<Tusry"T5:I~ Oe`|Ÿd q~ u~#^$^u0浱3-D:`MЌ=T4vŌw\|+mMGQn|�S΀:0jnvUpJbxqz[ EMbLYJ:`nl@<FKʽyUde;Þ[)c՝O5 ]Uu7?Z2Fv8K~.l&d̛pOL?s endstream endobj 664 0 obj << /Length1 2917 /Length2 26046 /Length3 0 /Length 27484 /Filter /FlateDecode >> stream xڜvT\k&@p@pN!; nntϼ7fVqoP((3%l@ ,̼�) ݜA hde`�p RP;Z;-D 5 o}Q{#X"f6Sv�V^n^vv�+3 ׿lyFf@+-B̑#ڈl�f(ؚd@пP;8 V|260b4GuSk?ɒ/S7L@m!'#cF 㿩ɘA@chP 45dbcP9:21eg #D.8Xrt@daa45!2J ̑` 4'5p7wh3323�I\ cou9pqL2r"t,"b ``p0�8�TH16�E_ 8s�;q@k9?,Cl?k5:8{zG_:9=0~_:Q]ޟLNVVB?�?{ ΅f6OMu?wT)G0+a"s sWO_X 6ݓ`33s#K_G@76X98nef�|a=L G \A{Ŀ$蟈$qD#n�o`q1$~#V�o`#p<O7ǓFx 8oT~#pt]7GW5~#ptͿXo4_CK^84O w,`lo`d xM0c[ϥ�ondc9%͝\H? 8$p}s;'= x n:q�b;*`f3 C,3[=; NpڲR;� r6Ud%pl~Êcp [{ ߚ_o5x1Z9 Xb;߾ڀ5 0K 8n99�}8&ـI;_'fsMhfcVEqt�ăY`dcgeuh`@pT? +9=n^#'{p[=Mw? 4B\1`Qz_%L°;b"a^#2wucc~ /RČ;cEK'f{}Kcj!];v)ws[Rm;#j=~ *Hau.rCj׊GUd,fE|V'\$2 Z8C5RӕOn`u,D)< hLh4i_E2IS%U3g$;^lCyv&MO2+.ʂс$3ett{M}<L|v+o}RmtPo1RFu9R9hO+F6{=T<GUqcjaSZy]8$?=e^v Zˤ)bS}q'Vb\dH=:G02Vƪm&6׬O\A8J)hSxw7y(sPZPF?P+y{BVTrDg9C:nW|-`(ltdD"<DC;b3cpDu^ptN-Պ`%5wu.Fndlؚ:L^VMl=Njbt`[&t S *h1!<<YQ:,ty5jU n#Xp%>,Ѯ +4Et[jqs7+PG䳆s�~:F,vf?DWR|ÃpH^s3w.\;2ul3֘Uj`8xEygezjۏgY\eb8?@6=7AMHڻ}mAtƈ_Fktˇ&k">{f_{T\'dfݰު8PPP.'fm exY~_I#lnZUה q<QǸ*teB:whA0N_MES8A@:Irh(z<sjD#pb( /ʂ8%n`{H1&D0hODsdG671b,~FyV~V=BLbv>ny[6-b! aIO39Dָ..r2X=Mtu yխ5Xz=VU&Uouh?ϿGWG`S}`<n8;x""ù\OVafr榤7_s.]KAI,[ L>i,7p<Su\4P6/¶o=`D 3M S ?q䦾w<N]5_֍td @.'I*O!ڪ͋8!:\s=Sjk њ&P'hP@h6HaA$Rr!{WP~=TV?D3 9&/3( cow͑~ΟeҤ䧷ٸ48(7TbUiTu:G=>c]G\5U# K؟rܛ[u;?u"\̴PYG2ނGm Ldf(Rxo yk~ V}E׬6:Gw|7V+q7 W :2w^zmi rb fj/^>k[G<mZi(ɠoǃT1.љү}leOQPJUޟ\"ڽ%BF]yCs9>i $n (<F_|[G9K^T3cΨ/޺JQ+0W)tI`r֤.@i/Ž]i&CWh#fJ ,w!#0WMP}#FyWiQ}:4"w3"/ddjHֈz5lm73 _wa[$Sa?s3xOn*<V t5 esې #)*$XWm8miHbδcC1ő[m] (.jV4h# ^NV2{pI#5P_G< c֎>xȞ/•/l$2%%bƼ $J~.+\;#`lS cuNe8$sD2擋OeL)?zH/+לIۥP~[.ux\uS3Pi}9`㓇 wv0˖{ϥw*-L SMЋ ]!QW-|N8bǪNePSYbj~iP>n:R|ߩ,ܱB|KgUwZ5S=UƺW\QP΍ xcS/vyR]5W#{N?Gf>qI^Q]f; sImC�+2!im; 5". tT[Ӯ=ai4q]92l9i�u6ZZG{:hv`G̀`=dp]Օ*vt0ˀwnDB0.i=f@}sHD(hX-UKN6)+߬Ex$- 9X1қzK_m{"*#^ԥ�i۟bͲ G[G$m�;, jʾS1|[b8n-3I /t+[ur =7`WSL]T|, z3b 5lH#WyEi0Znr>,h7:<|QܽtƛH%fDbl;H;'zgFk#;DL0#paF&۔iFXy"-Sun_ǫ@1i͜Ϧ}92t V h0wa]b2iz8.T9%y[jZ&q5ϫHbdfY֋=qKm_!(!Qn<l&P%~d|.kH/P:9>L}^zHWr4IMlǛr4 -L O3z".qS"3tlw+=;hv|J֎3zp{1<$d1[5z3Fyv\I9|Aۏ?a8OIl(!Š�<Ca.;73-qau]F#7|!nSkc;5n0ᄅL/7aǒEDL/ςEr46=5]㛼ƧbRIALoU5iϛ}Eg].|3<n%>kyD'4.mj zXaX(Ùlb+r~6~VFɟAd\:G^x-EOKѸsrY&qhD[*Rq1亗. i%}3/xDߨ3bXkeo!dds[+@=45>G|R&ˆEaEz49Ւ#{zC+:& w[~ }4,XŘp?:6DYD!Qs7ٶͯ(TFڍs I #"rQR0,4t^+3i<t;#5BQւhrl'z ]Ϩ_VձgY@gXFjJx·Cx8}ŷqwM*{iu 7=޻*R vz\Ptq;S9{DM:o&_P?QK=c!Uihd~ź&Cjۘ@rTN&€{~RwɼJn.D?l H|d@\P]ʼ/18{ZLo/kؓq~~d3i9 gJ(V{V6e`p:*TM~ʹ|vX5ءO};ans W{~1F6aSR0*.OQ콋mNCޥ=F 'excNn~(9rai𩝿 FsBE}�_`SAHsxKۡsCTe"MK`)Vxdltp�V,QI7wQpK\]m|*>kZC\/:qئx_�6n 7RxKުqY=[cf+#U0Ֆ&&Bq\ZʂݴJ:ȃ{:X\{>yghȔ2rr|+?kD9T%ߎ<{f5=ꓶ |Et H6۝}K)ku\ ZM] +ѽc){E깞V"aКQ"0>22x0҆c%k؍mlj]wɰEF%u[sliVS׿pY| >PXVieG_/^o"e iD-E 2ܟ~ G!&x0d"Xd zc,O1<Ep^_֔QD%jl'/8t(|.FOE*u7^ǐGND%¬&,m{7nX4tWY5mG;&uM[ڋP(mcqI'v{BOyp`5RY B xV J u\O463?Ʀ%3et6_hr)qn(W%9q�]h:|.n}DcįJ$;>&TL SܺMzAuڇB&OQ{=iV\AQ.rBm *M7,J3<bEy+/Ȯ˛J0Q5/KqI(5y{HXIAaim ~1N|]8S,۩(Ƣ~7ީ5Bc-Wΰ>ӡM7{X=:@@u[}bFį 2"zo2SN5L[h5I  �#CjLPƮ(Jkv4TS@pG Ȝ!`((3:Jԯ6*h;"( 0r:)HV<`dex(9O|MǐB񗀵h3B*+]d<3bA^д'NHڰ@1S 9ϳ1/FgnTIT3/ {UC iF;sS ]gaϊVfRh*. wi~Z̰*YTȠ,qGU+ _*˥WeoS.(ȘY6nVT eQ[~[y/+bgYze),򩗲$x�z`}]?f}?m;*T zȌ';gcźX$s9 Kb5o<ޑɔ37qWk䧒b}<8c#>|f!v[ S"Ϧ&y| Z]@voDՒ7Vj:vݕ'R1q�8ϾO!PE\6.5_~ag"hc~ @ \aÏ8}@48+.K7R7VMwJwO̟eJ! 4BrjCyAS×7#m#h׶\_se67Fh >}>a}rhxJt^Ҷ!�UG_h=�Qx䬡DA^6|&]Eyi-u饝)w;Pfz."Ut,Q=WZݔsV5> KAI юn;Sh2 * 4T:=twh; VXUN�")¼5äVDط=b/f>7BT]4Fw9/fţ>P)_-Vj<qPEQu\3ʹݫ4<Ify[4{=կ]I{ЅdD!ȇ=g&O]Ėu@QZRDסf0V87>Nn9$R|Rnp/kG│SY2ñ. v6z, )o;UmqnK؍FfLC3x ;݀U"㳩)`Ҍ1ߗc}YtQ7{ү ߲ǒ3y^' 9[tev"#q#`\R8~FKh"]2 M]|䑻>olVMmc |㔯Tȗ%`K,<{L:;wBx>F�˻-j+ NXK18q!\*)Վ恸ġ G D *A+jDK֦伬xUsOJI8msL_iI ?Fe \B"38G:DTZi 8ѿQu/*#cpG Oh~G !x 4pp9A|$@,Qp@4-?W|񻦞V63̤`v.Ȅ sԚ Ju7¹_xWl" }B?|I}eeoB@|IY~ׇ'%OåVm 5c}ߨS,ॳ<ᝉgjxZB@qB^=LJu9_r]<z؝Sj7zպDSG�ɼ4cbFu&8J,[O@I]x=| BoϾ&GPנL˝ЍNoTzxyqS2כv Cċr/̂uvrMeT3k&1o!xe *sr@d<6~`vWJ{ Y_-"jGӽdz룯`Tl5|(Pn5fu0_Eku2Q8߹ 3h&!e]T|"2L@CӃ1q:Q+^Ϥ4(-k!SC"2s,3A qsUe-dA.[x"7sF[?[v|M1HK<s.~.~hL+?sJb_Ɇ}t�E.Ur(m6pAN*?WY'yyk s֚͐jd*8azũވ {=!Q!y=x c5l鱊n jɊns�7iwʾae T 6 .ex].r)>[ϸ Jpco%KNfmnC3\_Ajb'u:Oǖw=fxSIė(*ޝ$M =3PlqIDO,DA_Y}yAI3 =d%\_#u4%ߺ `N,rM|T[$m@o sfQg|~Cuٺ+sZD~[CQzSOIz:g2"X}5V)̱]U?$;縭≭;3j7)Y9"XWH"/71[C$'sUBr]D $TgafJ 6rðɜK>[(�3א5bT̝]L|vXcJG9<_�ͯߪgU07X KIltX5y*VjbUm,lʆw3T߫ivyOܭv/y /mS.dCiq>WV@wٍG�7UŞ-fFdGl>f[•M/za0Abp]ջkjGΖBS+ksQv (KfbWQ'8Wv |+'QE*%!l^wk_(8z}4ЍShI/هlEx@0ȟC%Mt.<O.(&?z,Q4ƫ!j'a䰈SzpBT?w\.>ILqi7ZڭU7Q ޙ4)ܙz+FFɳnد \흂vQ[alkyo -8OTw q &p}hN~:<d3;&16ulFcA+WjKכhݭ?.`ړܬ1a][H^aTּ+&+cbnaqjX4j2& +/Џt(c3CVH*EH4}A=TeFЦ=>Qnwe㲘S.{F@]/ar{sVIe맏˱dб8 E-ԇhٜLgH�UV?@4g@mD9E #)4+)Km$ml_>HDʗ@U̹U4d{+Ɍd;ٔX;噙>P, [*I, y(5i % u+%k*Ud+d_d^O0C%Bz ]jrL*_(0֖N`j2'췎ݲ5X8b kA8?Q/{Bq[_ܘ3`6_c4?]^d39 l3Ю e*W86.!, <_IZruk `CdzsZZk,8!B1S#RQ~"A MTRcd}ĕ$ĭfZ0a�7 *bhL% Q/5[M'cd:&u-G2oM #O氉h$/u<5xk4o�QbIEFC".B?h'x7ٻ.2 ILlq$[$j%)g�;BJ>"�F69-ǷӤnLBgMo7. OߦԐ@#p9Okx K}_X |VgQ P#юя-eأk!Z'qv75g0҆ ʑ}qB"^~R["jw(AE(KPX4c;24$]|Ra0& x1$`9],/ ] ڳ%^!2F=EBUuU2ϱOX7�StKXK_];-4¨?`K=(5 )Ґҟ} Q+|Kz)l5?Dc+|kٴbpSQ?sU!4vx}&Ylۯ2-_FmBשI+u7/<;j3>#\? 6�e٬*,ʥ|dqJiMj Ѽ9 ?<0}\@G>EAIPrC 1 Bjͬ<"miL)P -&pE+h؛Z0s-wWt߾j$=zeTcss[n lScF.J85?eæ.#W "@Q%LNPE[kjc'daD_Nl=+4ݘ1H;oTct�C_ÿ y s/_ϥ>5VMfݶWK)8F!!z[Jc޶w-6R%d5B»[+nBRVjS{bT{;^Z?ā1WM?oڟ%r:h]HܟqgoQrK'.rCCX}bs ɛB~;| D=Q/ ]J3@ ;sggB\ prATĐ5s^yJPy@3%c"v#B@+}/aw#w-#)?01݃Ve1=h_=-y9{q JS~xw<^}ܮRp39'zi{LEM"%X*f+AQ] PVC % ,V!E9�I!găxZcE3Z v.sGe+~NcqНpLzg fc͛m~k~9|;-ɯ<5z|Cߔ:O$CꋻW ;+s!ΊMJH'>%F-$^ X߸v꾃~Azi|Փ;5=}.&ޢZ*~YׁIv7j?Зa9r#ƅi뙍%=Ko`%'ɬ{NbഩU~S$]\n>@pl=#EbENYLs I $4f𵠀{1:#3< nK9kq#mxzN7ɃN'ɬHue{TC 0=i5뾌D.F߸vQ3#Fj1N=scѐEN(&º (lE9Y]49'z @$j4_6-^R@rOIro?ԉqjWAԗ\XYGÊ !uQqRLa }MΈIf[sFc6Ec䆏Yy{<U<1[0|(dWyAvoxCzHG6]~R *]M6�okK8澒մZac~|/;IIĝAL=xR*l(sB2n_7˯c{G94d\,ޠXAIYN*6u5=SJ~=v] Ye$ q+cr473ӽr)d2];zIK 7uo[8d2L!ND7|R.EKB\[z]f?*1 w(W6T+93sATOIQlQ "NRԇc+=6p#ʒ<JQ_|%TPӆx!}`>;> ZjI,  +J#:x=S-M#N6JmY @|';Y#ݠrJq;jGgH:KRYiվ&C_DɂyUyt=lpBmcu {e wή)$xb/-4M'T1wCrСGnpY[ϻ� ˕F{5Sʆ0 _%V*?)7@S|>9=\^¥w:֥fӿ7pcubtD6P9蜎}9!džZ33e3 }oQ$g"0n$JXIR+_8)ۇ )v41+˸+|eeL)!6?B�܌UJP fG3kϣ \†V7E.$B'vaظzavdW|n.CSk:t:3JpzycsM3?bNS 1SOĂw .>{C \O]z!L8~ZnBos-3 +8TZ#f,mHh˸H�~-M͊~ B6ʽNXa l]iRVw,7I Cʢ9ip1(k=|*Ň @E�Q^m Ćw~\6y8@>6]G~I&Ƀ<tp*RTsl�B(c;HToHhl c<'kOh 'v=c3#hLd S!ͅM2R5y6D~=B*+BtޏBًBpL$ ߦ6f7"0xJ,Ϥo!xUy<,@^-x.D17*$:2B�1JרRyL%*V7RJP{-i:<o5C$UGs<G]&'b9-MON_|YG4EQ !ɰ$}M]oW\ª]1v*D?.3 >fk6V2-O ('O^=ͼM$m5Y`]HU�Fk6*66˩A-J<Yf쨸:$Z >V70Rǘ\(yxA)>.'g]MSmf%b;FcQ}#%Z S-E,:of:Iqj+.Pr+oU>+ɠ*6rn5k8S2D!JZa LO| ч<a.fGas:cD1'J�Y/d+ &XpМ9+Dq)^6B Vu k5Ry`<*2 $zL` ZTiB>gĖ}"o[Vo[i(Y@֩DP_|"ZYOԉFr,|(;a"m£9>mPa>ZF1i:\)x^'pNZGsY}#[-|H�jdU˩ δYa#y_ ֚xAɛ[p rjI*\)PZl9;Χ:$V{9~r+tv T7 HD�t!O8a od~~kiNrQ9J^B+Y2Rc ~ku*>INu&cTQp; MxDR))Vuښ{(]L;&a7>0CD7] {#z[.[c\TkwV紁@Hfɲ4Rx r~a9IAz~'[P]\(mB>LMRf|˱z �Eɛ&nG+S% oB}jo ڽ&U{q˜AC$Ʈh/ލ Izc⏂@>d˭(eblGE|L\%dHi.E"g`jw=~ܓTQ";LVۭl n6X~!.jXg%Ce#waP_>JRI9OvY#t%FQ;률KSژSz5[Ogk U{n̦ oMzP L=J;{9r X>2ж:k/4c-^>kmqhgìGi0_Nb%*5How0zJ [I!,)# &7s4㱞NzEⶠ`p.<srluWw`J{Ŗ_0#|9\\_DiA{ ".智98Qkmus+եR><iAE-kSixbSQhmdj&zO�#w\W{:۽75#_؝'*$ZDYk~q~#|h[U}T`?[jN29<Xc u Q_)Yz`qiEELbu2F]Hi\ltތL!Q-9w^q7r#YW$Zxѳ>@g :"xi| >Xi.8sHd|AR ԄA9G{iᢣ^XN|f,&I2 N|fN9]P33DlD]T.n;>%KVc|)iuGbX;ܘrͯJ|'5%- o1=]I:&5(0T3CpʯaWJJf B a枩!bq`۷W!"j3NP࠺r&*0*]E%V6iTELJ,Pj9jў <bfǥבu'wO&h*WwTDp*Xˢr_?:9]V0='x@ʟWBTcLg2sYb崹f=J`1'qr>$(+A)dBtqġ")GofҢYLV{;\Z2/86K \ `ہ*7]BZS #}.lք>[I6Ojaj '6}odjwj@>=]kڰ<ܱ2lt! Q,8y!A 70e7CE!ֺ!328;otǮT~vsPϴf1٪N>Jx:R6Zay2%7fv(j8Y 6aH J@>;0ȧ~uCPOe%pzBq�T[0 p"S&xzp"cSK ^9R\|% [7Cj;L=|Z3<NI1"VD [&~hdNb, FgI tHؽSp%;ʹI RɍݓjjiECo'F /FfYfs.sV3:Hdx7]McdAb 1yxD}ll|}*o`<6@nQNX?iX{cgWײH"Y޳AwC.[/KFX2}$tx,o8N6kDY+5ş}jkWBSV gW�a)=.AtA3e~hB^!q뽷]\tn @[-”s|TQr>|_2.UO~!XJXQ2YS_h*6҂7kdg8:chM^{JJr[8 nfm{3`a4 ln Ypj$|S.]ѿ9As*OZkqu} vЙ?ر10f-ɧ39$-oڴ\4"2%d[Wpw Yth<cW]ގh4.o"{N\c5[YL11 @jr5rY�Q'7 NjKj`VcK4*խrf3LAx*经v^O/ =9ȓ9�(UB)BnXnCbv |X XY'˵n{w^gT| 8y} "*8HBK-T\굧C;1NcDFblpD5z+GsI&iykot6YYw�7Vqp&Qm|;lکڢتW$w~gm(m+R͎Z럱juئ!bc$Rk=Pm,aU^P'Au9ų!s?yvGuEwpNka�lnh)LSF:F9KapƣQY][u`+Bzѳ1P^@-¶>K)q*c ` kT/H{ZZ CjYtdM3B *&hQ'J nEFSu 91]!$1Du>x#tS�N"m6T�%Ϣ~ _YօVkIHQ qk3v5ZJ}lizP[< h־ZR-&[:fN滽骺kb\ V@$pZ9/*}Vv1Xʕ7ພO ?Yv/s߈y)(*:V#/27l=*nP~`,4 xx=Z߳g8Cir\T]C^D-5)2h3]C1Ed޼yg.e1:h 3*a|ZfO >{IA8CN?rW/c756iMRu!/ZǔpVA<,ͧneޘ&Уy]N#cu~tpH7TT.Z򘒣΂+`ݦs)`0D`�Zeeg 0ZI|=PrIX g; -�N: Nc/)IjC9^ 7iA_M``Z�ƾo )~VMd,^Ewx3Lj~WM�#HJ"6(H^@vyPbb}j`,m VZ\6*|TrոR?)I1UHw�2XŔ 4=QLY@6^phhECk\'I} M X;|P0"+6n[%VuV~`(%)oS%gcL[}{P. X!-Pbk!1i FX%9Z`$ffѭɖoް@yҠA)gC貟C<pJac^L~7{}"tlf02~k3[i6)�{eEw0ƣΤC>%]&gYӭr(`ʀ72E0-*6žAP~,^H@R7'q=1M,^ζ#!CNϓ@mw*y#,CI̽xN5 Bv28E_d}Oӿnbt$LDZIIɂ ?Sk #� H~ȷ ^$г! ]Ny =GGNZYj ܩ\*f˩rc.KlbX~.SRnOJl/� >eaa&>x 2GIv\~4<g '͊F@,�> Yr}vbq[M t8E+-ĘΊCw2 &w3SpAoX<ݦPH ^ɪv6m"= b,( }7(=+qyC&+v02~x y?p-nĸn9H^gی缩8TXTgDqP"2!;rXu?b ;i1;ЌpHVx0|UP{3 Z:AE@lNi1n*a@@8Q1}P QpGD%?Qmxe1m+-Έ*8/p3N(RZ[B.^WJ%'"-CPʹ~MQb`K ]&<{Z؃e{_;욢V AL]F'kR]5Bo38VeyQ$c)H`rHձ2/R߅vp$ [bUzab>:v?]mMntִDxCV% UA6֦o+np~gr<-ka.W[/1g)iEhqyps0 LL`jti,;*%KЍG:gS!BUgH@4&gKR%a'I_fWF/E` ''5^i53Q1v6);svGKT{E#āI'菑WaY^qzA] FCu%p)s[xUOƨp]>R{)׈j(#˅/6TyaWAiәkܳ>i՛󕻨fն}Uh/@Ǯb{,;n->c-8QWZQSKQ6RR NzTJWpo<zdqpE>!!rGHFsf[/⛆\>Q|/55`DV̷JIayCFU'&clŖ4!Ea$ 7g&_IM)p]jUCs4Ѝ<#*rU 8zDK~-uǃQc(z O32dsJR@y$XD(D`7$,M6k{B84D@1p3=j"o͍~q3+Yci̾Fb;\b]C"Kr;`_5f#Th^D4�]%{Sz/"p;m̥k|QZ?{%xlb/S:Ax; qHxS3}oUHk:{%ozHЕXc<vkF,�;0#]V/0թLDd\WOQ]Gw6+edV\>!5;1Jx֎OuHr/P0 \1+P-G'{Ż[fI4U>lQݨ'' [5#!e bv0"E6@8Z~b;٢3;TnM:uUKѬ1.Z[:Tug7)a' fPOY:I ( GJ}QKr@6Lj;O`yϬ J# >x ,6/1nn&A8:ZuO狋/Jm[%RW}Ӽ$_~|Ҝ_as<SnfO]W n&joj w*Y p,n}u HϑÈI$] ɵWҮGds "|qW[δ4{)Y+jYJ)Ԛ[LdB ]ӳJ#]jǏipW?7~|2܈aLV*҈Ⱥ:lIZoL}RKY`d#I|"CcJzg/Ev"/}bwI@"i/9Søu1#pĕJ=e-Q2NfvHIOҤh_jܢ0 :3ӛS쥣]fʜL"3f0"Fn iKI*s1$?јfwl:�3>B+8 ga X OGn1G(@X pV%]!g8+=)|:F4*?-ɟcr#SxNgpVq6fWgDV7pt:ZB&|bVg-|@JwS\VĴ 5exGh< E4X/BSCiRd!0T˦Fy'=Y1#/)"y"teQwytUFv~o+89kH?*dPQaG� |kMLu7qH/ʇd̑3B�foD)Ha} Aq5CweG~ k/pfgOP ͺ/KN'kP+OkgZ%X<WDy{VD �l=&<ڻx-?;[RiG/ S" ?5%@AY9G7綊"9z%|Iߞ>A]WF8M\iTA&n? 9?h>Fgϟh :h:�UR {5tIn,fޞ\9myH$F=OXnL~5*I$CJT[n[7!!t.SV&V<7iS=p3[oeH;a^&uMW`9)++CTeMK-b{EaqTIHH"f7Yb^Ϲ+_1#?]�5,RPYT_5ޥ{\ӄcV+'~,1W8t<’ Q'p@FgKw4Qm'``e!NͰR] jU6QHxZ-<;I*:Bg53 jȫ9N�vT "r$з|qZĸ|AJ+Q2ԒvIUEW*^ۜ]h`~ S*5 a $Ō&O4@QTQ^TF(G֚pgb 70-э)Ue0M_Z9@,e33eP FXL5D ]Sł^=DSjgCWJ Ƭ,y2(,uXV鄈Wt$+u]BD:ńM\\O%(m,Z86#SQ}0*vw7B1d}&{~f>ȑ#6#QMp0E{@V|!W|$Sch%ca<겇GNsܲ2YXm'#܆.)n^H!;4NJ# Q7(cEDfO8ˬ. 4B()9⏯,S~_E#Qc.TD}4|fM"/g a%8vl_AiYJY"=�KT szs{8>V5ºG*kY@A6Ӈ:+\(g#(?_ݢkh6\<sA& }5ڇy^AfB\(_^ܘP 8VׁסeO6`?l;3v闣a 6LF.VwZ\ܩ<-oH'h> n{lc=maˢ豵lpCR<IN �(S({/MΠoXMr ӧbo|+6{@0VNJ@d33|;ѲQUE/ ӪL8MD͜ZGgT|).5zRTeL3rihS(_.cVnh2%eȸNN/fe`w@,]Qb;J�%^{t-j" ~nJ&R{1Ȏgef&`s@Ā:(PpcfTIoN8 &p'ٙO%u.S)=j@+xÚ;!;2C\jw1{wü+?Wo#V6i9Avwv5E~t�Sd/D<uolIӸb\VsG]y " ^/ _Sa&X!kS0SJ`C9 U9ΕoaCB�T LjJɪV(M /y@y"? ZˋӯGc~kyh >UC §|ހ"Doés?C0=#O!mM$MA)OVL/vQ zv(x0uSv"z4@lSۓH{`]{4pbYQ4o/×JxE,00)18>Z XJ0 3v#0fLηQ!$b V�#l^/腘6e'4Kb? :dl CQM(,1yH9XXk1jI"U 5WFdֶ\$+QJ.{^+eE'[&TQP�O!;6PKlKK#v l.lQYH[jqe`~ي0 ƊeKj5~:~a! #xJNεJCs**W7^k3xŷj'Mσ5(DZ UGt\8Z0}+Pg]oUzT׬=.%7W1_1|2�x7#Iӯ3r꺒T<ѕ(CU.gBlۉ*YlTN}MIӦo YS2῿Hn_5$g\fӞA){CWEP$]>7O8e*rpw8ׂz<�˹<GG2;{k/",H-+  j{c?Xv %o']s/.Jf^-;-, ߭4C Zn]-7k '%zegB#gEmGTofznQi1ł6lqU&l2/q{e-e_9,dN)^k )愆3؅@<z,v{2wy9cC}-ۑԥw:3a f^>* 8-P}�?Y[@|+Y!qUptԥ#Wl$IljHp7֡FX?Jj .IAS>>i#ͫ~L]&&5YkNW;%XBޚZ4·bAy"Oܿ륐L &n0kl] 8@jH}I@(E7I*52N+ K,d:6Tǥ>w/,QB>$zM34s*]E3<YYz]S9ԵUTp苉!];2 U@"62YEӧqxI0 #$9 p=y`Fkrϩ q6CĽwHg/-<LjT1:1F`ɪ(EqC;TտܻfydWq'O&u3}P 38 v'{.lڍs=͙@j?fqV-C]WJ hzb`3P2L7YS^ςTӮh{oJm y\g6"g2{οC5΄ngDq"u7>˕I[mD 鬲X"9ho l8F2)5d6wkT$5'㞋gziԵE!˦Ct3PowVB}Zz|MXSvϬ{u�/Vx*\b߁,[ENݢ}}˪ N^sl9K$m:{BxQ14!gDVyi}FS݁v\Q=2ls#[; p%H@뾮:᐀2@ޠIUfbfuKEýK(>wLXD`>W"iG^"d1Jd_rJO*f9DD}}V;+>QaCZZ>wV㷐r# u:~,AKaIT)5h€(Zx[9h+.K5h; F6VWÏSxrMδKOc7<YFY% اF.Ij^>)vr__{s|H2Fx �5}sUPs9ͶUӀm%<Z+ێT.8wwNu7"s.Q={qo+ePI qyҫBh`[c'vd9HiTɶSD'qN~íȸe΄] ׄ)ඓ' ryQ'㺤7X*==J(ԕte=<ŎRղ?58#j@nCd {wx\ G}o]!IHؓOZ*?QBP9W ד]4O!)ҲkUP%\}2Wck>8n Ph}V�luYa4N?B_ I-M9kM0[[4ThWwE2^WCp_`M�@CO^/('7<ΘS݊n.7t*'u4!얊n(u#4 s0җ6Vז˽&wq6أ k-yZxk" -0-z<x:8ո#2rVWsgX�Na4lh]Y>ڧRwŽB\w[R2&dzZ):30`egO#=#U N{!͹ׁg4Ow�er?BtΏH#y䨂Vws'X;x(#QyZJ�Ӿ*dU_' #U)pٙ*TCMZRP[b`T0cǰ$,|lhOZ SϘm.U^Kl@`%ȝ7Xbp,[�u|f/mu[:郿LHhh T]!4L hۮNo` m tfv 7ApD^t-cܒ^q˿b꿁<?Y<ub fF8^:X`2&}n W 9(Qu۸ѷ& : .B_+QDT+0d@= y Iyf$fJqM!:DzQJ'Qf<'' jxE QYןV驦5 Fr"P ~Ul&laC&  <ivOsPxþ% Q|"vq1KA$5 K%_P,-zbA@q_|sgf=#.>dggk5#NJ{%PڀQ hט%n;59=d<,qc[8zqE2\p,Te T;HJa endstream endobj 666 0 obj << /Length1 1144 /Length2 1528 /Length3 0 /Length 2250 /Filter /FlateDecode >> stream xuSy<Tk'EY%7[' 302Ⱦ a3f.JR]BQJb(*V9~<p!3:B K|HH@^-POS44 \% M!3MMX�%bmxZ| DD‡"X A>Qa"AXHx\dDg"B+1+|&WY#�]AĆ#t rt&TA>Z4s:¢gBvP#X4L,SB ]3i̜!>@͝[q?,fδ6Ptw'alPX��p+c62@gH4Lx`Ѹp;џb B;E`B !@5|SGa5 V k�u^(o>H0fn_T06x)"o1WB;B�lľ  îWALd3Ep?5wO-47˝dq�\�xӽsiiWsYw! 10uL 2)5,fμ87 `px.1"`P @7C0sN0aB0 Q̯4xf.=eςAp+P/AIg'ϐc0nYXm,Zn+t^fD6r)m`9o9L{c" j湥i0=gCT~Ф5EkcϝWFWO;T&#񺓛Qz|%1͏(u#%[҅S.x^Ѡ[ꨂJvU}E*&6޼d(۴dzt̬]ӣ뫻5S^ّX}Dkm60dx0t~zli^Kɚv󶞆{k'֩#%ILf=?x$6wjVurhu(237k<]iu4Mтָ'" ^&?S^PZo#fn=q-ޞ'IS 6Ɖg'v5+:+E-%F#/7삯O$1w_H\W8PAݓҨ@BT9>2hZJ?U7[qf*L&\꺪#oXl-Aih\Fѹw)}ʭDءx5{b 2+: M%w:~uxe[ؤ=j*/ާ z:V]q[e"Y)sa@&YDtd[~Lwp[:eMY1uX|ƹڪ~9qluL,a$+o[{$mr>[4|x~p7>Qi\XZT< 0\8e@<2}llDUޭ\Q=D-)p#1ve9k|U\3)J)}AؾގWuЉ<گ4kli3[}!FW7=81&A[%E R9etI犓%?Hd)g֍{}:drވ>~s@ҞhReQ? {#nq69WxKKԇn7r겜p=*VmI.xu$ #c|?M>ՙe:Y`{Yt2C eͺiۍ{6i8U捞5 K֭^]%+ ڍ#VE\~E"Pk~%lLs+ęyoj UVHF`iͶ8QO 6kKZ$M sSC] ąhv~B1Ja:`:>LcKRa-4&w([nR(UK}5*a㧬'R4>o R:`4V̷(2語rnxjo \s͓T҅ اPPhy`#qRãvEjA fR[SiNuC%eNy՝թsG9޷h{cdE>!Gm,)hi|-M7Q21dՈDZêhEm 쩒\h endstream endobj 668 0 obj << /Length1 1626 /Length2 13044 /Length3 0 /Length 13880 /Filter /FlateDecode >> stream xڭyctenl۵c6+6*ޱmVmNŪmۼӧOs?||;Zc+ L$lx�6F.Nv6vܲr&@ \VلaXX�p�Q;{G 3sg�5--ݿ$�<t0P|>Xۘ:;�M�&�QE-iyI�@bdma 06u29q�-*͉3doblfnlb`ohc p9:`akl o@v6`vNNƎ΀ϬblnWn'O5hgWI>|j -l�&22�- =>swٿM &NNa>c՝ /[{mbpv26ecfiY503CtQ53ԟ v�)gJ�e=(_!?rr󿇖p71|,EbXX{ZhE쬁v6l'-L LZ8IX�-֟[f 4q5虙MjnaleP'UgQUQ*F,׿ ?Y"g_aDD^\�zV6ϻ Iw  -:u31]u0vF9i)KmIߗywcy;c Ԍ4Z육11f`|jn԰M ך` 6?o24{#=X֔&y>Խk{z%i'Q^sL{[cJzůP0dH)( h' CWٱ伆ؾIĉ Ϯ j.2K ?MrUk4~U [joluDlŔ\jg$ Z4ĥA><D79CMq23BʰVֶR(7ž4YPg.*`iu{#}x0l\Ys%Zcg/45G6{ٓr}h8< JG<fLզH=Iz}%<FzY%?w\OsEӲg_%EM*X^ pt`@Mq7baenYP 枥1bJ8ȱ)X̣%zgt *D88Lͬ7*8fF[1t zs 6Vwtg1hNOcQb;[K֕hg9{/fP76㠖t|}+9.϶{L`ieD];Gwf\͆)$ FAHs`wF_6ŷ wJMWk,*x)^،g Phݸ5r0ݑd/Q&[ :>, v,39eۗ$gQ߄M] Ԓ*a}yOx(7UOaH1w(ٳ/^tyvZjD[Q.9%CjfLIkr� 8Gvf[S?3`?}jUQ+~}q$13L^U+ Cq�H'4w >6ewV.C.?u#U=~^µ=^HhotVռT3iȘ("=rK0fC6{a`(.X݉EoZrqT?e/9. ESAԝgѦ0ep>gj$TNlՂJ 5ǿ9(_l(<T󗡥D|�;۴QkMaP( I&ʏ"p0Y33e6wFDN$8s%F_[*Lwo ,A_@Yv"pL7|Ww2ˊАwTئ܋:v V&A[W')Cѩ3y2_M]8*qXGQLvdU 6)?k03?)YX+9F[d<pd6VT\"g6bѵC ~LْŚ Ԑl`lӜ@f_\e7}Bv#Ə}8_hj/mLW\ߟp\EbJTNL/Fiٯ\CwTw|Ohv(s!ai[4%uB#ԊǵB QhOb_<{~RU"ҺKI#c7-wܷJ<4Y<|u9]B6[<->ײ^B�[ |U:at_b^Z-{uX>yfQy'ؑna~\<m}HQ6 ̈E;O鉊Y/Ȝ .+ƔlGL~_ߟp+= lA%ǽ՗cojv0RӬz.r)d-wz($ѐ- _x[1^L,3 wcۋ t>N9a%\TH75AtR(?|y ]W*IځZCIckqhC +m'T *|g ](7-C cTo8} \"L4 Hj.JѵAc4("ë.6XJ GbhzT#݁(&.QܓiyUzz i6?0"JʠP:{2)*:IgYOfF?c*dWУv>L{סZ X!ėwu:U4-6 JCrЖ{Cot&ztt6G:6?&|G** _Zp睉2l"#ޓ`jAN[zQx·QkYQNԜU)3kgb [[dr~ON;j܁78O cj$Dp[iz0E7n;ԮT|94[p>Ĕ%9bP}H׃c-8~pnVH;i]#H 30%ą`Ođ/i,hqg1,Xg8vp~gŽ>AԻbQ>g\e,͖e̮T5v<HR=p?ID[Ll:>&W$jg`d1YDW7X䬾m,ꩈu F o芎^i#3|rBG/:Cwm揇m7G%[6K-SkкvZ,Ť!=+RUS8x:ҔpPF@"j-„ %ؙ@!xC+==yJ˦ӺcKy-׵H\̗<f\H<i6v!CHn>T UcH\$]r_Ȕ%$q,W{TWwU?@]f@-Hqk�*ְgiTĝhfDɼ\ kq`g iܥ}OBݮ(J"vS-]li-v5mT,^R`ŕ?w<E7 UHryDkcm3/⢢ Obnܲ^G�EVo3T>S:tk nqdXŤI$J�"KH47^Rqw̴q([ݾ0dMO@OV{Q%gFUҍwF=dȰ[:B5'Ӽݢ ]\/`\)r5?O  Sb?p |Ӫ 0g_M/.fP;[U$7^qS X1l3?`tJ !_ GƓKB%=_e'cצB\ԦN+AMI [|9qa) (B7jf~cԋ3:w @,^zJmkx dMkR:"jۤ򄙈0oFMx_泮Q<k}=l"%/A-̀X9ts0&P8vĠ-$h=#'�v7&\)P uakP9HIЪ;sH<nbuD {q ?ǬCŬ@CO`~*4U_<Ά¿'ؤ٢7g{RZUO)r$aakLO"%|&n`Վm#}A+b j,~'iye^&}֣8fI(eX{T0nC)ɡd7aO䰔i1M5Υ!0rZŧ؁—Mɐ5528ŲR,zϑXxi5bp]m&'zA a;BkU1zV{O JbcTTkl`ѵЯͿd(hi ƗB0U@poV6wϜPᕉ0JN*q$T682M 7vO#(B&F& qSG1i1OhoHb YK,TE*~Jw 볽9hBdѨ<Gq)~j! 8y Л#Á#I:eE.kD:srO&;e �Fnm>�,g[dבzZxnܙNj!LRR"W.@r|Ur{C0'r;NKl#}5v9tmX2>Ss/ tl̞&eS&/vttAð]竳;x@?~ pIhSX ʢ"/ M1yVc ktdRN~meͮM,}yj[:q?f.lCP7j6NHAR}SʏtGhW> VC<-^xNiV4AՅeoy|:vjUN%R  W aHNqg'VY O !K)AdX#|: $A5<Y8ܤ2h+ LVq9#%ȴ`c}~+%1"< ,PbݹL/onN ["*d¸&x~O( #sntXsVGl`^<:eM ^ehlWb6;(3%4QO% \̕Ft cLnSzbЕWr1{6fJaB4A@%Z*'$ }Q2Z$O6y"ϧɐBbťE%jYE-s!I2Xac< $KXѫ dfr3G"+ r.7:[r=�vvRSKHN(t]qUmi M'oSЯFW?9 !oj9Z ΍ VL<Yl:}~쾗ɑ𚮦ŮM* \d>uH?Y3)uﮚQ^mƱ$}e5H<&A3+VQ@7xZo<Dvvjg0Eo4'f#T7iEh\Ͽ-7'J ȓ$ %wLd &dum5eF hR[yi-Q]g9iP3jIE?ojDjDi魗|"0<([,l0S @ 7NX0C@0!Q җU�bo8ReWK5"@NNjdm,-Bb�Mc4Vx&vL<?\�_mk�Zd_EYĠ뢳"p:"*m;+&hc5D+|"?ق2ݳFNƜ>׍Y;$'GRKjPjwϜ>6}ب]I8⇍2-21&4t{l~i9l`5ƱG $8-XÛ%yZ>I#BQg BU "SQ\0~VM;1" ̓ldɅ{r%nN)y8lnƤXs".ҭ^z_آ E ԓV)I- nlG&%2%E؄C`>tMQl>k~UtvٺfGQ1B8Xn y+8f>򦇦W&{@chY/ɝ?YL |db[9iQ څ?$JjX./˜r*sܮ?;Dsnܘ+ _t^x k-b\]˲sQ*2 E\` UBgMB`G*X s/4Pc $T5(V^D5++m;-.lTr 8oʈuU}7) ݚB<ur{fH? YY�r(6m(sK*/`> Ѹ#:=q ha=Է*1̑U]I~[c ! Utv^OSև7ZˬE!b eL`CGsgllbzNî24@!)NIzƝ9bu.#5V6>33Ok¸ʩ")۶[BPXp6ךr]SC|\Ybe{hTҎ2"8yQt+g)>O5dժ<NB1]eEjOSJ[Cuϼ8>M۽B5T7M:ݏ]%T/ўL 4sva=fJ SS0ҕb+c&BHZO:Qn +ik?tĺl_Q^{ݥ6v/y. h1u*&:vSQDtt|.Jy\(lԐ˙BxHȖ9j1q*3Cxj'5׌U2 (ӫ3`& @[&~ ,K3Z5>fhiZo9Xt9ά.Q pdeȾWxzYK!){sWԣ AW@T7ro.C3;` uhN$B1X78ҿ &w$Q!V(qB1tq2YUzլ;�Ž|YJSF>nT>"=Q#h~4/1O3Wլ5g&# Z>W GQj,g[T[ߙwE5<h-;~UnM<=ڎɷ1T% me`4}渡T[|!93.7XG #]?EgpVgwdHrij7GT1'f:H zeӑA#2E^1A-^eYЪ:I4􇧥eh6Bf^}hU</†U#Ei@a\YuzBpmw]kBXl- `]Z9oPӿl$� ޵eϱhpc?-!l~W^}c2�"ʈ@z9͋-)/`KDŽqͪCW$'Zh#=m<%V?8֝w\L5xg.s5ȭ&򁯨2- [`%!J5Sq#4:^$\(zpfw]n4@dB도u69Aj0$fGv@}*:!M5b+i=紤IA$nS*9i,ģFBPiuA~׬wͼAϣ,}λti? !Li[R+m-`}j{l2G}gTIT}Z=M>ϴE&z uw5wC]eTIž<>FE/pקaQ:myCK'\� Yߪuqs&Qm޴*jMV1YLZ0k{/ ?ݤg@&,jiOFtaiFxΫRE= FXJ^ۮ#ۛ1ODmb& [ԓTPkgU=QGBYS+vJd=,j1r=pGk&)k7vXF0OFa!(<xSl1VZտ3Z&[3o|q4lRaRz[w rpUS RRYA+${ *w4@$P=lA#9a!\뽛bwn|H"bxKt9zas+F$|x|wiO\q#L;ȿE8BHLҶl"5ҳDĸrp2\zkD_^.4w)Zoyg]Y$idxm�WM<B%cmg;NBL.2|_NUwf,H1ua[j?1ξ-'תQj_PS]a [+LN:4 y_,-09^OM A!TG$HYv#^*:E<*F]-VSxb^-oq(A=]e]N{OHSZy_ϣ;Zs)^D=BZڪC"3c20GRQꇁ[J/ʙP 7ʺlw CH⨊. ZÉ*QlCYcAēUF;:}l{IۨX*rW3_oLd!]xE.b9<gѦT k}.xGGхlHc T|g@sTsHs _ /CgT:I"hYl0H.KN1" N{>X.0P'hS)tkA%OxO$2XgK&H;nVg0w#oW5r%oڡ횏,[xųIt[)gY<N%zP^?FTRPESNݚA>Æ#wW$g."0 @�Aq[<D-M>Z6n(wDLu5ߜTamb:bW}PD64 K<>zNbˍ* GcyN.I@[B,<6-:{>석xe-0L NL墬^v:g G1\8sSҏW ߋ73RxMKf<ձb0rVǷr^%<șBN5ш"?8~vXiK 7!BGFwq{jzI -\k=a$F'~WPhuҷl(P<=D3c$*Ƨ3r|+�[``*}p\ |^>C.bU0o wgP3BoĚȯ% ÁD,K*Hm_Wj5X:A*'S(-nYa-P$R=Ӵšfb5(rw @'ޜE.(^0&IB9L1bFڎfW-R9V\yRZLL~ lk.ECZ{!Bb*Vڕuq;cS+azI 7 GR\_7?,K.ש,T *bG'H1<A.#D P#^ ΘXZQJpFM!@tO ?m_|܃BHOCꂚٿ7İ"HHo? ;n- {߀< T~ir8Z |a7~Au3`Yf뾅˻5NQ NUv: - hn[L؋1,iJsOX3$WʍZ|ۗ A:efpPBNKÆ1}_ͧ7?C?hUOE{-O|HN@3=O\GP̀20%(0*4T|[¿źC Ux /a  `\uY57Vjp04i4xp _Lz`ES>;W\$.OQ?(<Cz+iuUxX4YԠ^BOYjKUޮ(eΖ ]ʩKXas !k*ξ6R !Q�U䞰#R4XuTb?CyJZ0Ň7so5ṛ.>wS$Wb+Wmp*[Ҟ.̑0fM#g7ǜQWܩ_lMIyEb-#^K 7A\ t dqf]eޙr-YR#7gk1 K(ER"(4ckQAqެv'[믲e. )^m]zVx!b\كvf''m?u$Do3RUJ ѧrR'wS75 Eb1jqOgLYm䇏)zk{;":zo14qE/͝&y]7m;|S�!(IK$t2V} ABmb~Bes3z)d MxOa}u\|^xCFq4` u[}g,}؇EZWbIlW%$&Fy]4UMQA*3Ev4 $OY3kfQFJaCƢ&x1U^5өȸsJ J <Da[#q!ߐϫ*:=J 2=O̔ܣYX,ugCٚr\o/s|$b^堇D-_^H$d$j8J �Z hT)T斺`o4o,~i tPғH Z%7n/�j3aV7Ѻi<B<`e+([AVv Y R";z2F,qDGB**1ĻO`>e9̭YyX=jIy Jg-cҨ7B >y(bfUjJ 茫'X)PA2':P &}(8T3v b;x[/Z5n/ 'TWTț-};Ѻ@;( `'(2̂U*Yh2B5ݝDoU-K[O*JJgx^vyַpڒU YܽSlLaIi>%<I%xY57y)͐;)vC woǃ(ύp. !ޮ.QU*mIWB):tWb t`z � l$mбHoՙp8_O�:%۴¢sb^c}q1nׄ!@!Hii)W3ԯ5AW' EeSe bj8F"z» FH�}(I }r"]a>.vODB4k">_Fӛ�eE_* 5C(>}fYQ',c`j[Nv;qW<umoNJtceR}:|NcrʂY3Ncʫ-TĔ!w֙ t 2�wK ۭ% (Zpв2sV~Ni̜rr v�(YԱDqڍjk[e$R+(t+zLYŷi}?Z:8\aha e_iƀk?S%2#38 4\ rI)hT$ <WfIQjDw9f%9`1p3/G"B68!�TWV;jߒgA"+)Dy#_.8O�r==A ?Z9߲]U~$8&<ysN>rп/+㬁=MGR@\<tA([a ~أ\ 5+҄r쑿:CG�i W݉/GTMWTMi!E`uF ü½r8Q<eN^x􍯻%PHj95x\NU;Uc(ge>!9*?DckܶZצa@/Z*IUរ[Ga$ M(zc]#iP%MHMa+keCwV8GjJ&0hs 9'3Pnvp&W%>\nԯv &Cԩ"&7 ‹P>zbB㪭0-1,QuA抏#b{.ki}nKg" +"AGqTC@rl= @IV k[i'c',ăo7) M_M`?%(L"?@ jC@9eDW�|g{�|63mG\ Z8k߽hۄ_ 1�)dλaXM Fu&c~7/ENPj9qqH |$.HJ]dK=�%nY+)?Qb{W_SvWE~D/J9?]~k~ >ѮQQBtJ&uV! KM^nC\ Mb Z5Po)j�0&uMZ tסDϚ'/tܤr�WXţ+ VT]Po+q*0xd Bo@V)Ζ{f䜝:uX](t 7&sKI^(Cv|Q#+v[vH1Ȩm٢ER ̓qETF5v+o jc?=h$P"EȾ<A7Y{]yTw jԦe[h(c4 endstream endobj 670 0 obj << /Length1 1630 /Length2 17603 /Length3 0 /Length 18438 /Filter /FlateDecode >> stream xڬctem&Tl;ٱmb۶Sm۶m۪8۶z޷O}~1=qM\kI h MDlh�6Ύv6vҴ&f΀rVhRRa' ;۟N&\�5cO#� lg`afPQTO?&�Ct0}p11u dbp27ZX�5$d�b*�1[k@ф`j�`dgklOit�G{#n&nF&h�&6�3[=pXY;_ݿwkaWL 7OdnOlGj_Kc;#J/_#X&�c G{k;X+ gG [̀`bf`lm/?:KڔoL#,l [S;�#ÿs1qW(ʿIZMLeP߱LG-FB:[[%c` g�Ҁ_LLo[mR@o9o%W56q5 ed`/:es #+H`VO/",,FY2;Ns?0BBvn�OZF6�-7!N&M1Y nU?~y/0"FviFI[5&&n&FkvFAiNu#S?AGK jz}v8+?jfݗ?$Э{SLq) 6:٩uKբ<h1N)(|t2;@^?S<6Ģu!6!%<? ނPBr`$&9;<4};V-e %z/;<0_2} 3,J^0%L*Kw-KhJ\匱9j\K#.bBRZ 7We@LWPeg'჏H(tƇVN>�f<rx aBuXÿǃ ل.T1mY5?ӍT*uO$iD%Kzuګݓ&�?{<$U 8!s T&#Òy hX;DyS!č xfA#sWO q_C~ԣ7c>Qj�pwjFbj6G؀JLo@$UnGCyd.Vw/}95{&ch.ֶoLߘuZO3/23SK<׭,Sl$0ig"M-E[-fL\>+P,?L/حQ-@YH^H,XS/(gOA�8OϏ˧9ڼןW,̎zn,Qwf|P| E ߻"|`8:98m?BsWC4e)2t%9+hm9NI6}VN$7~2IM_7/<ej#W1|bʫe|hx8>rЩנ o}P!T<{8(SazPVYney۱NW&V30qlt| žg6MS921oy7Hg[aaF2ձRZ'fG `psH~,S }aYCAa'Z+wcHF`<|EqC\�3{I\SIB42M1΃{)/[?z> +K%N!_aR"OW?z b!OF!X [:?2vp~�N%]WwMZ=^Ϊxk7d?awyxL{'lUsT'NX 0Ms ;?߼tT߆(C'|QxAs Ђt is^D쇼75 ak̗: Fk+;ƕ<b1:wAG1|YńjqWFi. H1ݤ%~j(H<|MaJQQTH^ޚDlу$<dlh>W/0 Hęa J F2BwV9Xb\Ww* Ny&M`Dku_qwr,Q vٟpi+/jJ`cYʀ3<=mE ixV~E,3U>\nȣd@j�{l1X-ګu/R\|pYɒEC DnuvD/A#獶&:ϿfrZR_.=! xG{wO095VNGBھE^M#th\[z4s =ѣua,UbѦ&uFY%-W3vs+Rj;(^И݂g9NUa5'd=HqQ=4 Xձd|Pn2q*2Mth@!FJK0^{9bGeDOOR>*n%S8&\&lWo gZ~fHD)d|Sao{ˠV%G꙯XhyN\3{~-c!<Nlpʭ$b"zQbF5 Nd<9<Ό߬( 䤺$ĩVAy FS^ݒ箘vDwVcG*1'_ ("8T4*kqvq@c٥]h{)Gb<!;]9I-%GNf$=τHI{t/Β%¿ԩq7nРޛD>9 ;$d448ކ0[yҶFms]?;]Y=۽ؼɭºR0Sv ̕%ԟ' „Al򼝂M3|X꧐NWr) ~Zh&oIݸsiqLV &R8H}.ar^u7φ{(䵎5!`zEkU`p_ 'TilS$eNԃTbJw^C  `s[J jݲK�'DQUh2K n(K05Jd"cY_1R}[A ^AdtMeŏZc䀩-3l*`g�^< 텵&@Ag}^9%f<WBe)1Znȇs[gXəРrh#xr8)-\P_.lT\ь ~ ʰ%0P)c-C60X=QT) y63”Lj}%ѧKܸ״,UդgR_n [XQa+;τdQI-sk$aRqGʈHƩONw7^bʞiT_3 d_ZooHS/~/RgB},.F^xq,axjY~vAN~)p2P.9B?[,,Kus{v}J4y \@ Gb | !QO]WxA?VU:l:Q,)EyH'{9yDş$FsJaGtsa3bDŽB21& 5!'qhJ-#Ud2 sgΞ2pPw7Ezb}tܶ{H"a Zod<k$O{\pMTy <X4FwQ.wLmTknRB9V\%?7O4jVldP7t~j-&D'öY6u�%V/{pֳp@R~rW/{N3u]0J0)JjUzb;Sfݬn 埔! \3 >L-x1 -kG,W1C[07{߂,+Cأ@j6 tci~Ԙ&,(c&ժY Ys槾*SpS:V&E=oG,Bĝ)�`cr)]s8a1)%T#KF*RO4#Pcќk6;V&9Y$`y.FgK*LءlFΙUIf]2{XdO9;׈r$Un;k[`׮A)C;qs"}6I8 QS95`Zz,2è>�?+y~B[ނ^õ SOM捬e:Z4 HZ<,"˧ڸEaL[tGW9{( nOFX['z{Kn(ýdePyL(1\gaIv/4W=(AƢ:&&sptD_3OrA>gdj9o<??t FblXdԵ x>`&_+P*̏]X)Oaah8q*b1gy[(hW֝sq񛛺e\Eo4"HKHpB1Po;Taw^Yq"')͜δ́S\T5K_]&yŨGo:壳/|3+'"GEo^=*Ryx@YoNzcKg ]]vGVSl/˃@h=<%%TkL PDL5ȕE>:8s`V/gd-¥q ]=;D#Pyd ^߾H+ޛlKz.=,[V_}} 3Ռ6DtC0zbA-8llG(ɱ{ Mىrd6v!+ ]ϩSiRXt*{Y)QYvI7!:Q󾘑~j3kLn"%>4P}49eH ,LRЂ/hGZ'q2"Sв**q|@BPxS7)!k;Gǹ!OQN;VjEᲸ!jaB.d|@57+tkC,>ڤ'Y] g~wd;UE~;esgĞqeOI4Y}[qTNՠJq)C+B=-4ږ2CayzɏF-񾣖kKmU b'a1dإ Uq" k'X'VҾ |AL=c}uWMˁInT30d-om.�8yW`˸l5k'YfQxs +^>^HJPClJwd"'$m jvNDLJqm:Jg[|K KKbCMj`v&rʿ1__4vwU *4` 藲.l J겠=u�9⪡`̲V9!7XvTNYȶ QSâmfwXG5o,o/[9c&XNM|g~4 !b`U,dH܇A+CZ8U$8~ގZon׃Fl/Dp@(i/y>$jA{E #>o끦n`%I,j!A.ǔ@9G,VxnA8=)^WJcG .\ ia>7";\jw i$7oOKcOJA:8aje.GO?i q hR7Fzˎ|Lf7?rv/{ھ0]\h!@]Yp8s:t2|Hh\1 *0?*="%]PlyXgRYPc[kg1nrS"hK rR#CcUF׸A!Bh+O3/yW 3ɹ?dʶ 17wEcB.zoAkEA>^s 5^)>w`;W*;?NT*+Qt{ж1ir aezo\0!5*ߌ=GG](1gm/\ <Cro|h o L)| vTjӠgR(=ѓ 5�3׭.ci^T h vZlo4٭^<d;`˫G* ++ x@eo30HʬuvJx CՇI 1{ kHU+y,'X}|ز<K=S7bC}9S~@Ex3?6lsil}&$&~^#K%i^0ְ$WinЋ|g{RԨw\ {6=c~FM'6b ~eI{=K.:TO|_M>ު<Hb4-!|FB]ϭa (iUM BTӅ+F L~ `(ICo'w{JnMă(cw ~_TS,[$O`Us*l,?sb_WK8Rք% �!h< q [EɅRPnPj B!h*Ѱq!;9\>y}C4lyg[30D6t"v%G0B.wIXAS笞{埊l۠d1n:dJa9p1kc`u05˨78QP |πoK˃zI' &z "1t{9tGr sgKػtl2r1hIAZ¼nq.;�6'hp_/cqgfQϪŽ:T}df;cNZl5`Z-$уc~ 3.!ovb{[m1˗,Cv<5%:{;iÏ18}CfCx'/fra&:?B&sc䃑)NҤ謴f[F1ѷ͹Q]6AIj7(Wڂ91G=/5oT"[Sh{QaiBõY" / OHju{4Ȧm[|S|7%�<1O%'߃(-@<zP c틁5ǓSrBtUگp7}o"�-EV5teQQIflG}n@T#sh]XLZob?ˬmHŶ-j4ud^ASAvX�?;$T&/Wl1? =uEet,U- ahX 7e¼C ╞9:r Ni6; `бCٗmtNk/ν@Qˇֳ̟_э_6GEFDJ̙iŽ5I`׺_+#-g p@ϬvDE<AQ{f5%|612}%؆ڶy'Zt >XeǡRxsL*2t5.2/nS=WF}h> 3ԵZ ]ͱ}&'Wl{XGY{ .^йFT&pxq./s߉)๝?>Ŏj9ԧCQ^L-=$!+ L¢A~,33ClHC{qكFk(I\; $˲"@$+nW^lP>E,WuUwP&Uk'5@݁W6ٲ(:@ozʬ8ؓ"==t,9&oeٜuBP Jo՜Ug.ȓ޸pvݿ2GǟℙR}lXBA滭Xk]b ;e Fl(r<b\n%W*IG+&m vW|78Ϣ6" /hRSy9SyVvWl- ]cQ:=&"eyB k?ASyfËILؚ~(*|ǖRGbb2blW}]~25xW}KTfyaUlQŮ6rMR4_/o7X?iYQ+qp_O 7IzLwHQ)-!}pWW.Z*X<dvyA0ǿ DH,gHSX_!S>2"4J*bZv-] mk2L` غ"fUOַK<D0�IM1*IWĆk[T.@\djlͮ7gǛ5fc˚U߳ 6@r~θB{nq Jεfu $؁G[EFrXLg N wo &(K>6x6;]W/SVdWtp7JŽ8"pizc?f֌nk{NnE8cqhO@o�dg #>) ՜Gtl"O>X6fgT|HM&4ڕDAMk?:Ezl"1/{xW)qzּ9@Ji 6z-=17nt}w[_YQ7zI=0]AI-*-b^VCN׫a0&jTS0 Bg U^`Qo%>(;tޜep0bWx6X?lji\ŏ` Gd]C r3v'ˣUnfy3aY;MhrjШ\% Mr\<f܊U\ׯL6(|q4֫y3upMTI |Su ֎\N"l89ː:QmP#jAJt]x,~e"& ؒSCm89x?'NGQYi)T%s.a3F}\t>|/|3(C-e"?�!h;9ZWB9D^5on ڽn&Xi(̹Sh#!\_SOYNoAyPNl'HI)/;߹U ;O'x;8śY8`??JDt5܇&c++4F2-)c?A_ys*֓=Ok4د=UԋTi H@;7wj.o.LUֺ!#}Fs1;FPFI!G5NxL)1)K] þwSx1@FQ]z2X|-͒y._$@upO|Mܞf2Dfjq_@^| g}^60@VYXk';VmƼ}o9cU96B�;T oҘ V<RP>JҺ%#M"F՗馄H G4 p4$3Z98K%2W Ȥ@z V}ڞLI[Cd-IRQ1T<Zl_iUڞVҶ..j"nhFe2[ߗDg6+%HNvBs_io7©D!닏Mf]�42XlJ<%#%ƫx,$D.Hs=y`IDt^} H)bG4+(REt3Z'G1o‹ D ^Mf: [dam<}ɬpnTA`ʈgU'6H㽘O21k;TiWTLK-#y&\1wp^7F40H\P0?B3g[g<[*'%x$L;4ߗ{q;RIoj Lʘ K ܔRx(B"\XHS;PC<=ot~b)˜,>/So }uU1@.g3lD sLJO yUD@ǐ^R4/$6Ad'fu.Jm rg#ug^٣R& ~9aAxA|h7/;ZtG[[<[/A%3-j UbfN{#)>:fP ʕac5ɕs.(=#L :L8@)(_aE;b.ߧybV;D,oU*z%?U~]\=�%gҲ.i=8uFΉ?9<ud;x 7(~^j �Z.K8kPH$2\EmǥǎfS˅\2[}U,dfO8"р$�elklGRVc<SFXuPPy`I�qvoDWvj7eFgy6`5(}-HD8ݛ|,팯$yj݁LL$jWLEw rNt]% erMAprBgrݲ=3bUv؀tbR\8 8%ڹ'AҕN[g.%P"x{*NjF \fm #,}8o *g Ϋ"Eݙ*l�:F!pNw"(X,>\Tȿ7j0u`zYA=]0 ZH܆ 0?+Ҵh6lc`U�g+auM@?$pAFpuu DEj *-Æ9U_Nܦ6B$ς1b;JaNfX^ 'H~bcUDKYs ")!i%]{�N,"\{紱! sitX1OOg`݁c * )3:^q7zUJ8topoFlJ[ծa%i>^ GU\6%֊ ϻ܈>kP`+5>_ '^:&8(&A 1㐴QG>.$Z@.0dzD45M. bt`X9N  <Ko>s!>QpU)iekd)h;<#2mA} W3El+XGZy͍S4G=h<\ܕ%�Xh܅2P䊅%5T̰JノYTҝX1VTnɴdft_|=۴X+xV79$@c]Dr 9!uP`},WfMhy,_!)[XN4-RZD^]lB@$Z͓J 7ю/Gɛc.@|࿱1B\cǾyRA?]  Vȁ%RGIXD&5`쌙sXMUÂ;rN,az[':X@α{U2`0$(8Q"JjqA3x5H~/ʶxyP*=FK ^` qT d{T^(Б#SLFDajOp{PSG S,=( ΂fSe oz҉(jRptȼ:R*] >T:YrlW|Em2{: i։~, Of؅Zf&w J>5aD?N1I6琅PX<8^W+X@MK^'sB6)pT``%' YR_Yt:u#T+OX ޕk 1DDCZ€}^S FbF^ŏ15I`y]RI7~TSl4Ӕ=9yIU+IWf~nU؅F6]7x<Æ3 L'&nT\=X1_܁rX=nW XJx}Rs΂6.G**7(b?(c'ZDE"K%aM C筃A2Kyie09>y|ޏ OĠA[: (K^(^s\vwHpƴ,b|9e#Ĺ;vߺH/sѯ'"Й.1 cg;-|Y+{%]mpNlw)|TOj\ bG2, IZ ٘ o_C2^1^8)Mq=ϡcB: ^ ZU ܱvl5ê?֥G ^wLAɻaKWPu(V)|Li-___v6{uQtyȠ!OR?7zG.?R>b <N ~[KB5ȰdbV�b@`ͥڱ/7M~#A{v._yoBb1Kfyh  ֟S4cĸmDCF:H GHmj&vIJJ[S9SNcͼM=DrHatDgp_.hkzFkq݂H j�K^6$ԓpnÏ+H"D Pa>y[Lh"o&HAjKC' M)@hb~-hOjFBO/jѴU* )u}pٴKʢ wA3ЙT3N*d<#]U uu1zh~݃<qA -F&po6r߻ Hp\wy'>Շ^PBaJ&[y.cLBdC[(ssDrKsZ+|6vp^ݽgj/xGp ȫ0K'(5u=qpOA1\'z]qJ4ϗC\ᐚ@n�{@pڀJQ`ew/ lp+ٸ8T=ᲉH@d<{[X:ѿ4I0td>ne~8YKmB(5, QD%lՊ9H3Y|e C>m%鹯[+2YP6&h}j!ߥUʪ~L7VSTRmXN/k)v^dc`=wRw=ۿ>ۏf+! F? LUz+5Ŭ8#8KqJޱ0%NZCSrPs)!D3,-EȻkMd `E8\eW勦E>68u@s:Ug9v")xnsd{i}s՜P"tVAd"ح8i & (npQۜ8n~’_74uW<9|:6>uei$Ʋ O>ѿ{U بT%"z~%$gLu[dI DU:(N}zCpzJ \-дvZ6 d6,G{zdb)Of<+̪AԽQf|Cܘv4I둻sd>]R#J`|W_?SK!TBk-h8}W\ǷȊYT~ޚ/ȴu׼*Ź㚍ߞR~F`ޥ֥[/DZL1 r*-߹,YY[ ĹJ%K)QXKOo%rEdٕ\b}cdg:, |C`̧Z6wYUDQ(X\H̅'dW'8]\pfCXNaCFꑑٖ./450EseVU%Ŷʐ1'#3(u1RFcԨ-+OV9XJ;%RQAj,҇pOHZƙ?J,~{$bGڤuScJws{l�,}SKSEfuckB/sh'\Ze b8|ݞE&.2Wlx7i*pPFR9Y=M4g9~=ΰ$Tx&N PCf1u{OhxwaɕΔ=9SlG'%v hNSi!0~  =H7#p|QĞYmE [yUKb>D򍛹Ur.[8_4Ya@Nt{sqcWtf.yPQ0lHPCm}}^GOs@wA\vT'{DQT^[z˲Ս* Aߵ7F+BǚhLqv{(%=} W݀QL\@x51i:?jN"ؒbK\b]5":L,a T+"ڐgt|ռMNۚ26s:Z4f$ Op*}l_.;r] Ӎ k&ۂZw(6$$~ӡ^9V]Bi5~Lx#Z{f K`1;P@ i,|tK. $>nϲ׍ z`TcfRX(Wk.XU)L/z$fDcEu͡-D?&>}R|EfsJu)k舩EOπ=/kf=,ިs:Tei"Xn5Maʌ+ m]C.RݬRpӬ R<yM>x{tH|Q/Y(w^Ȣ|" Evᲊ7>樧 N!{*ɸ8A0UF<NNL�U8q8W�Ƶ*Z(lta8RzV&17njO<rp?M/|ۇ.?=uѨXpv0lί׵d_>+-߉,R,RөJJ^N[,�Gr0Y4|`PƚdFm,?I(&q䖯Ki:#[-G/S'*I OD}~-?베B-UH|B2Y B<u5c.Α=^t"wj!k6J S7 #uyk+JbO3 QT[qH-&jöۦw{okSR$pg9 PFU^oJgc3La>ݶLkj UNtp t7`DOleg%WWZ7.jP<t/tBR(Y@n_`J-G',K4)0nb7Kr4K2-P^ / V4C11 zu[Ob<K%X\0iZlij;:d5QeXn4Xc2Ez?`]E;;T Yp$DQ iMwEtj=VCqxt)xIgZsjNa|{KvC0U0brny+� V$W%2qUrB*%Dr 9I/H[hU׭C\hWUOc5GZYAKH[ ]). �t D?,δ+L=h$ĚCFz~&QՓҠ͙JX5/7pV:WZ:X-fBO+`:LCְ/d&:>dہ$rq&ؔd1Ư2)qzTJH`deA}}Y<6dbLY$hP¢rmEqF9s-> "&{^8Ҁctf|JL9͟ǤEᆰNňƁ>UyCЮp(V }Wp,I]~KEqd0+= D3D5yj>C tν_y=[_UAG؎N6/UH!p-DZN`jJ9.~y uc㌥e1� jwD_\iiwQ)FѧRjd =p\AВvb:;S͛v3ڙ[vQ{ձ:$\<Tt՗rfo^cSeMe&BޕL/T'F#Տ=;Tz EjFAoÌoR-G\xtoHx>RNSUk['q"NqYR. 9cJD@ VQ!%+*_)RLh*Xʾ;N-&G'Qf(yĝm 60™cnNpS +:+k4ҜɟzO4¯H1< :m!F=U[p<F1+`aj9[*Qw6sAwtT;nUV˸W0FxJ+ fzN ]$d֟N-~ZqwNb)UB�Ig/vmܻ \REl]̔Jq?քq{uea$r[M 직ϔ2otXQXb7u@Y/2ƴ+` +.xVT1 5"zUW^&'Rm�!jbDIWo'z<ERj }<Xs(_ռ"w RL%ïc8 /xnX:m$T񿛆l]r$pSMmO/Qywl Ee)>L߲]Kp&o ⩜}y̪lЮ4pk,vȗ#́]r~o&2F]3[(<93/9R}Չn֜[}1GW V!51R^DLܿezB>-#JJb'U7^i`ub'$Y}jJ|_;`e%],²foB.M!�'Jy<U?�dMgGM[5"*! e?�-Ϻ] ‹9D(LhqnmVU: �#uLe [)f"_ߧcJo.*{.6O{" gf}EZIŒ2+ki⫃`87ZCpRx,?Gp �I^߳FӰE IUê7l5|{<nc|B(0y%T $ٰ~a"קv.4k12aPG(>,Un/:~d endstream endobj 672 0 obj << /Length1 1644 /Length2 10401 /Length3 0 /Length 11234 /Filter /FlateDecode >> stream xڭweX\ے6h5hMxpAC!9gܙ3{UzKZT`�:9ػrq!vv +U΋BK+2s8K�: @dp = `+�#33˿$�=ytt/n [G;+PX�[@JEUO^Y كl "d bX:8l^�,쁐?9bI8�Ύ ȫGp9A_g�.�+O�rKrtrxa{Supvqp8�^J;N+3?!jN럔ҽ¼j] �_ �hk W{"`8fN@[+++O/kv33֒ է˫o0O[:�89]s9U ?=�Y+;0Xf#O#9O<;;W[[e3{�^=u�1zOV[wkY$԰ p8x +kkAN{+o:M+"xV+e.._,kpm. Qr�sPR'�`|= r7Z 0`|ѿ[8�4=)purzq?duB8:=+å0oxRڠv8ıfqC_z`c][sǧL{=2jƾBt{e:^g p|{[jƥo;~1S:bZ5wb5B8K:uK?862<s߷KʜL+lF23sbvN-vG҇%W M\ΌnryiX(j,Wq ŸԌ{OK+|?ĄmVc!QKż r Y @9m 5=(~O$oie0*Kb;\|ȑDj4>B`Yc8#?pY2G"ޫWľ!IH Y9e]e+<.:wZ{0lvByWW)-=]2oMgJ<?u@+ *?a, 56DnVfKfDm' ܞlӹ*HGy?}c=z_�Џ"2l+3_S|ZCzIr_osuAvsZϫ"_| vmJ&ԛ+1t6㆐-5ުfԢN*4XZ{ <7M[l "N7sO,JwOD1G. $㓳6֭G#M**YZKJX箆 > T'2 VG+µ֝&=v6lEKx^}Y3#T+6xZ+'S6=R 1"mݓܮ[ _Pnc˜M7~o(FPj? ,pY[G_}~W(1u`Wo>16;HU' f0֛ʬFM�JdL9~⣓f}ijlީ.-N~>'{w㬦7SЌ~4(fŒEXDq2&~50|^$x"a9ɤ#z`3�Y]b@Q.\aY$]`X尵&Tzrc|˭S3-Aro$ԾF 3~ZD4b+-ק?˅Oyf!x/{~:Ac8[7S#c4'#LwnO<D5x,/GBMs- .LKfQ~E"SqsҗU@0hO(RJ4="UQ5ҿR �%004TM?wO e !=S:P0EGzz2Jxh *;cLKe$;y]Ny񬐚[+0,a%3~mQwr.15d='H Ewϼ p1I_Ьʈӥ4u ycN^߱�V&Y6n1ϱ^!.X#_n^BY'Mδ S3 o'#i-kF#F|zTڢ[�p.'*!Ծ]|_qT (c!#IG7^3  UkB퉍-]+H*3/;&ׯe;y1aTz S=dV=? ^θGr 'Na4 #򒁳+ա޽ݧd BY2iswEl}KƒL)S|{RaA=_K963L%&>K95e/[]R6A*4|v] V _cC`\浝 V*3]>3wlGcouyDB-b8E630CF&A$nKjHOhoLD*ym�* Ř$f~PDDt3sn@eB_o{aXmm]ubEGNKҜ y{+0,GWzcNTd굂rL\67yh6)g*'m<ZPD<ޕ+3pMy"?Rts_J.YTѧzO|m]աFZ jh- ]0h})K<9%OE,k3cs~.k!�k4z˿% t*a*-rA˖� @s 7+cyӢPrAW4]s#wg2Ѻ㝶(XPRb?O?kٰhO?\ݦaZ 1-/]rO.9xa d3nZKhFlu�OX@-u8Z80:$zO΂lsd(\\pn,ŵ#'0_N[؎zx_f,"2KwW~{*pu>kly|W4TVU`ة%5ãTDP�EzCf]1 ]Aedph/9ZN,gt { #R݊hr#Ic l`;R_J#4W4bZ ܫ9M:P"ڄ=9ö<Kg7?پPO&x}Laֵ] JĆPAz)Z`GlVDêEZfFTE킎/yf5lY̌&0�Q8 %nAHbBBh*y8]Y/+O3> ZYwJFWHDzN7(lNOe4H!w(_cTHm*І~+rte>'ޠTȼÞ\6hsᐙum(l7R›xWOqdZv]&j~U)*S>YÜ}LZ8;.>(.U{&_;-Vѽ@ZCB #M$_ʪv>6X= xo꒙!Sa& PCy#-:](mSF|4͒ͷMeZs11NM<*n:eIZO["5oqb2 rH:/;d0"m(Ÿ+[O>gg> z-!x8ݟ*:w ~@tAg]2)Za Òko;j6F+4;i :_M<ڏ;:o%|e?n|jt$Om,PwUnP $4ĮD=L|J!ra%#35fUP:4~ot~SMJD0JokT2%T?q\?`_`Ln-oETi"ە ~96\?`$OVZfxl6t nU Jv;Ԍ1H t^L;ѣ*!1sSSd|oK .LӸ"]>R0]\ E-@)Hs5S\AXlYKHBZ_kt.f nБB0}Kbh퉌fdkr~q` Fy2mGr/PӁ; @!2A*E9Zǵ!"gP!nu/ڽ,ねـŘ M,rf֕=`S#Á. c#]lB*f>'vGXREI:Hi#%,(ei e�c&Ǩ/)j=~Y)$1^B } j Ep3[o11)<b֬ ֒mv&d3 rJ2_@nPR(NVl༾wȖ? 56QyO N9 Yⲷ+FR^Uh#pB~LajT^maF==x"�"6 (can t']a3B& NYP /NԪfT^e܌Xcͅ[hmq ^ *j~jra#%E@ly[Fbt6 OpJ+^hESU ri M1Q[E$q,5jR7EUğTւS{<Qhmo} ꩓lI y8U`(^R4Auk=4hy}׌Z!7tɛԑQ"bZ+XlBRmۮ.<Epf]=әL^Qs $<RS GKuX[a3JɬR%'k 5J`P6 c͑c�N9 ߴt+UPX1<<6;3Nň ]Vn 7jU؏i!߲L[F42[%eO \+:4҈8j&t >JPBHrC3:F|Ng";rl{CR =ódTG)vy{GG70?~] L7f0{>}*9-Pem `!PRh.Z]vt`V�v׆k|0Mkcft׆$f!<;K* nC|`>Uk +F\.!WSFEs=y̼U[c% ?nE`[ŕYB=O44vJ XtI*638Q! CZ d(oG/TF aTCpR"JI9*vFE e4prA< cH�b_(|S`4d7L`jucnǗ4ͥ5ZAeN<!, N+mZ/aUBR<҇Űۤʇ9aJ߹b$"v4mȃOf,E8\TDQԊQZ%`iA%U"Si^ۙdU^xT2?jeĒ[.s'35!&J/`�aDy#>Pl,z�U nm0Zg~ܤ4o4{#lh9�kN%�v+D#IcT߯EDG HlJ\P 8ݨh}hu _p{?yq_Wd@r-sf'aХC?yMdLtm5E12KKھrmHH!؍dSKؗ/3eeވqKL8`ω b"OtRDC.-VrĜ )F n6Cfm񄫓xMfl#-QL!hd,.۾Uxy%nHT\Z۲d]J�%5qX~+eN;=Öa־gJkb4hI˔ҁ|mcH8ɚ*OR`TigXBQ[H+? ߖ. Hӑ?I{}J9Rp>eЏWeGZ9, ~4*fhk'ɎG٧K"]Y~ykZ2KX*^Z4'jiy]>˾k,S)/t�W7Nf.ԍuKY jɸܽo`9Ro 6uZow=>i@4(�]+ێl;|uY롋Z6?& kY r_grUW!|@ O='L@V))%yXD ;Ľ�5k*<� oOH=7 )S؎A3,WIq:=v;!(-V//6wq9<)c IHi2]zR5ghB5s&.D 7_Ħ�RE;'gK\C%'3 :\[x(Vv.%7{ 51t,(#Y(pUy񷐝`Ze|ȸc3_?,Pv g9]yQ 7d+ЯG.&%K*/=Ƕ2\B ٨o@S,'@JEXd`Z#ak =Z?}qCNn:87ONZ^AߜetS@. Q -OBFs(a!Br3&((/$K}_QZ+o攦K,FW^'>#L\ `''ƳƐLPk7I7#Mzb37mNa~8&pG+S,u<ww~NaZ`Upе6ҡ)2I*D|o7mq$TÔqtTd_Om:[ZJw?.z+}E_u!.}¶d}J. oQQah[*tM)r^-ζNWl4/iG }]#]3M6ӗ A.HgnLFp9-養@0Ix1-EWhj;)ssl6Y))ȼS"Ysv'~8*K�_o[C#Ϲ9̟nQgn7;bfnK3vy WxL]wM mKotp\ ˁ+N�}avЏgӱ>g wR~ [P/CMiU&Mz&&r^6~T xuH?C=xv<\y![vLBA& RqDv+k,Gv澒O̥쳿e(RbُՓU.0p!]sOGv& q2 'bk˩ /lT'b[Z*Cdd!o?I[u֒Mn~,1Hg GxIWк:spNG[O]!j(=}_sa4ʴ0kPOƋl] XncYOQ@D{!?�HjhtY#saCXo_+y';ڥ&/r-rz.>uD?iF ^F3DiI`MYrllUwsFz~ d߽ ɂwPeh'(&/ Igv#@ wթ`|͞*؆V #sv׹MkKO3[YɢP޻eS/fQa΃lۢCPxaFMg,">AdaeI w a#SiHh+ 7mmNf/pG&"#Ma|с<Ttno(3};vyg!gT~$JgIe:0Zʨ wN}妺IwcnD@в( Ӵvh(C(P8("_?\ɮ,ChW'`_7F>}J~^wd Bf  c J.''<=Lh__C-4ȐV_5~62]hkUYxvtWӷ70Pl% Edv غYpI $O]*E}my\,}֜AtgbԲCkI1(W55muf&\unyʦK<ޚp\TXmcH }Îӕd(6_]?rE-FQb*kd� ~eH #IG,K9~=Na(R^H=8cfORB8;ubˊFxvuf/>$f! IS}m8 Do/~uJ0jQG)#zKdԮl1Eǝ ;a=?|t#Pfb4ҚcWpe~ h^5OGzjI<IĜIaXC_"N]׬W H6xH-86'K~43dž+>*|5ӣau΂\ktCFJ~癙W^l8g~7icD�SMg �]Tmڜ!G#;"C#Ƅqkq:'Gv JyLvz3ЋsD&(>5Mj@o>j I1S9ƀ5HuR0u_K/GO?%G6`g!t-.}DgE<w[iU/x-Zi|9 r]wI?Y!b} @?^&$WP[>#XvpEIu3nWej g՟4oH, Gv7˵:7u5 9RTIoG:(6X@[e`Y2;4637錬yP}uVT >&F=tGѱKɕzlo؅_E8U%b>ܺI᰿ eԦ4:$oܟL?vJmf1UX9 ч}eLԅ\"{HCbjE}faze"Iډ>A6@Xx4I?ޡXf14GYEDJ{7D3FS(kDĜ`XO@y?{6ѳNʣ R966f(p ϬJEKo�e�sz.XO7vã$>e 9`=%LI"hճ<~-dow7UͮL3Y=LKTEz[u43kǗ@Wσ9}("&q4c~ϤlZwDQ=H^\<�Wɏ+!^=Rf"5ሾǁ$0ɦ JA0.\ҙ &/h~E"­fGg&;kҍPDiЊ!Fh>JFŬǚαHb)8\<unRji2~^~mI<eU5k.n,<s`LJyY:ĢX%AaBc00 gK�6dP]yA_tcqh#0ôrl),tLtMWVBynH"A`_rO7I)Z5RD]98M;)Ig{O֙ 2:t?{}b?G 2"?y1yQ^x䡭 O[{EfG 2ð8b &vT,DE{vѸ~}V\BQȱ"sǭc94O`Hg¦PS7x]M39^(pqpET5I:uS:3M"ÖOaTQBW3u7TTy3M~�n]wU/1gl\2LJMrǕk+åH^ _O5Ao1۶+RB]|/@$U Գ6'ӧfjdWFO\r1"_vM)$ UXrAyI}.LK?Ў6r T1>vǕ9}I+]Wy�_@=p/GҮ̽ ާ󘢊V'7Xz2 94sߥi9$`]S]v&fvd){mz`6X\(`0҆3t%XJ@CG4#MiE#ȏ[n\~(nܱY"#v)bdcfw6mO1s2wPI1KzuM"?߷*_ 2sCsp}2o0:׆9r<EMYz{t,nxt[bΙ%pl֩˼+wɆinO&dw4EɖG| 8Ȇ]h,ROX$\@DKSڲ&ub82ɗT1 endstream endobj 674 0 obj << /Length1 1647 /Length2 14164 /Length3 0 /Length 15019 /Filter /FlateDecode >> stream xڭcx_&c{wl۶ѱc۶ձmvұ3g\}[uWUZE]QN(ngLD 1rqR㒥SH9Zblpdd"@Cg ;[QCg 7@hL\\\pd�;{G 3sg�: Zqy7@hmgouḰ�S k @DAQSJ^@)!�6bdma 0:�v��v&DK `p[ h@G '� ';pX[S_ݿ waKhdha UQTu::/ 3ibgOKE -l�@wr&Nֆs%wW.NfY-hfhb trK>[ hmJ7fp ̋v\ fo&v�)ߔ�;DoEyo=WjqkkyC=h mw @ϲ6tp,?6wN!dkW!:&6z--܁&�SC뿗/ W F[[ۿ!nA^JYQYmw*U=쁀I]sx1s9>ƿϑ',ghfgddt ?slhkw;4[[3 LLw>b_ڨZT_cUi^B4tfq M}8 Ӛ7xCBWEAsȠW~u(poRIY`ʟĵ8! <bpldx�&'dgLJFO7Wx7/�[4;zWfiT5&Fs>@~{wxIq A?##minW oqJ );<uC VVuJ Lx'a?\b[1?Pc;n'%r#S0,(d oO5* g%kw =hh>zRU# ϭL-5F"9!`WI9Ԃ~*=BԔ"/tfd+KD*gVUCad+MRq#| F;%,AqFѣ0[1Xw4^E?a {}σyյ7@#sj‰RW;(R3au jiσ,5w?QFFMیy_=)FsC[|P濞AmVY}ԈJ$Vy4dOOɭpFKZ#QĜT7Չ5cʑ&,rG?tsq3ZZ�; I#+j=2x.ʵt`>izD7MYB6PLr=̛U ̈jo8I.wyZ(3#*]͹g{'RBSpH4 gIo}q)88(DBiQAg'-ɐ2q S Y"Dhd%nsC2U<�5Oʟeh _ â1`ؠ( Z?E4v-"7;Cy疧235 {߾3wo¯{M$b~?ҝn_Ȩ٣z*^%jپa'$Z:LjhDq: ֎ϮOLI{V l[3 - QnM}z- gNQ66$n_f;2]C=v0@e'+ 7*#S;Vr7dCgӑ+@n�+ǢuEϩiEu!aSh>P9mL 1ξh‹W3^�,g+jf1}ʌ9kc ׁW3zٜlvxيPoGB]rL@�=NÇ^c/F>l*'rqF-(k b $}y �5pWwC;f/j#a+BHLeHOr誻/ӥzwנ3e_ƽq.Me,|R9)-EQ| jt[<60dn)ELC@j Vh:>f1! @"0Qhτ*b\p Tt&pIXWPmik7bY<<[7ZZTmO%τY[P�,\2"I@ɱUl5[Rm~M}25,R{ɢ7Khp} FoRs)]U@xr'NKw5qߞO%s9 jqMD* {2rkHP[@ @s,?!ک|=KV{y-@^q<N_i<f@숔eq,-B7$rY4%f0 }M_hq (kF7v ?rSNLʑ>!փ`O3_h2=flZb&%->J"70Ce.z?3EKBxC POޕ+?Y#Utv`i$Ìt取[iND2z= {X@fh ;F"sF<=SHɏYh@|Oe<S2t"x<eyNQXuFWjZEg"hN!ƕw<_Ү9F<Sg OC}<Y(9#b6Q{;_{7bD;#?}%A,-nhC{ݣR�/m~T)%OFȲ1UуM[Ր,] !vXƚ)M/Q'tR\܅RX`CǫpB<EZqvNoђZ٥)}̍b3Ha]<p['x:va;8{r[4k8Z0=2|02=mË,eOxy+rM I,4֩{a܌.>BgRVIɓP: [˽+~| Pk�˾zx }iEFf;ĕ'QPdaFcT[DA 2IXgX>1Y_J`5j}&"~zݟ s;%*qm2S~'RX~cH?:D I=>hTjj,kឹs=Vꛪ{<MQ }jtBY+g槟m*xʳx`;g쑊EJH.ҘgbL غ 20>%_$:2~=$d w (E]`x@<O4 iYT%zҼËŘ9/,9|W4dҰĀs 9Д} tj nb蜺;2wk:;"C$"/p' 咔urΜ.`w`Z2nf'3—DK1PS;lv08]cJvECNqUƤ^4 '\wèOSEc,`XIMcyMpA}Z}At =C W RZczn!sn 5g=!xhh}wח 9l-n:ɓD+ZujF*x(. Ѫj$*lSFbneVD]8+F^ohOWҽwy*LgCPdoBf~1C@܇ :^T!HRظY(IV5^M8Ì/_*Xjl?eFl wȏR{6\8x.ki> F׎¼ +sxM)OA 768. nZI?C,$ Ǿ go(uG2BWC('uY۞7_1Z(sJ=T-uNw3IHwа"aNQ;<ip{ %[rQwxR{g-GYY"K4F0yU@ΓuhVaalΐ휨 D~*2ŜR/iPJMQPuv|P<~8G^mX4SJ[MrqIF_D&aw&|tFȬOA: >}EN4tfO9I�,F9L;7 KA<wK]E Ū LQ~ 'Dh/gwvWj[dp\B |0\Yw,-|= z&[FtS7Dxta 3`8|?<U1ZS#AT:0GMdD/KU; d)%r&m{XȦ|E6#8ixX:`lPS^ Xg'cpkŊ2'tplr%w[xp`ɂ 1dSO|J]NtT�qӪ tZV_89#Gm͎wnո}~z}t&!/a)6l&ku^ z; ~ >7fOxKGh+ABzțўTݠj6l7y7NY}֛Wٖ꺸lq|*]Mk[E飝8"aMl]d&O;t=~)$6.x9D{/>;j]RXY<Bkǟ?5)~TSXP!gŽTadw,}D 5; Z a򜭤!a. [gU1~Pi[{vHzr{:ʒE)6 F +d!Cj#GxEqމ{# }E]χ&#^_oԑ숌ȁSҲ!k)Ϳtzܳ5/g0tmN4-%:JȰNJYۢa#%;BKO/Ǎ $x\ܺ<@( { iGQ)Z<2|9m6ǧk&]QPDDς('ƍ6ju:T# mg"~%uD <?,] տ`xg6pK<rB N_tJ꟮h/4U *NB2~]EUvm!wbx.w?jgrYW,Bu/YvWb�.)<E-!yϹӣх[z-+YPzwWspdfıl`5wU[<>:]'ƣM<۹95+d`.!Xy}q< ǤoDxs}t:Z̻�6Z(o ljf=ݚPElC+ZCL`wc~cziإxpcAtNBp:3_hI?V({/ ϊ}VpͺLT;Ej9xW&cn1?($nWI 0I6٥YE\FieJlObw/r? E%fBs$uo-klY&ػxX̱K! :> vvsopyV8DnuzdADlV8gCSz{<JH-<dХu鑪ۧݧ)ӽ{j 6YE%-1TSI16 ("r(/{)Fٜz1صTWi 7/.D{X/y4~jHo#*C\i^\0E CiIɶ ,'DHvC0ĪHY+~PR1Rw�&Q*6'+_]q³(UlKڔ4MXz#_[^:C@ػ#tSS &~NA8¤&oF{*^ݿJ%ۤ(FcގTuN|e8n65)Š_K_n;LU3J9LXP%k դRI mBs嵶FfJ~}&\Tx:7}拚ͅA1,r9w+_8P+SRs`zcޏL�'r/HVGo+Lw_/0]>N^x0)}{rOLZ"<:򌱃uqy[\j"D)vn k4VحO�4.\|EPΩ#R]-m)@AcP8Ⱦ!|C KN2imH+ Iu\hϊ|wY ]Q.K^;D;%yϕ;֦xA+<C V j%^W 'mgA:NÕ g-^w�7GGtol y/-L~\ܥ7Ws$lvadcg&`|t%MBefޭ*w9Y _KЮ1Q ZDHږ--'3|Qﵨ >oh( f+>"v9q I];05A-1a50G# H9`!V?WNrg+#Ip[Xt[!2_A9M0cX| ?Ne#m#_1} ճX>x) o޺WmYh˜1+YCݘh؊TꜙImf؍[.c+g& Q/ n*;u-Muܲ_@ݬL B~nF *T?P@4M=ڊ|!"iKīufC#&[=/6\U_7)'Qw‡R1*~+͟Yc%e {Cf<!B⥀iBtˌ}9$1GB`O t&"e iLʵEe݁WѦ1 F;we5e׃tt;ټICnӇ%qQ:2YQjN?FiBR*~9=.ov\`.0IIY^jz[.Z;L kXz*:X+ U7=[huֳ<Eu׽YӦ`F@^tah/<o lqCSKJ0I4!Bk2Ԃm做&JLM*8d"\+DV2Qjof.#3@Tqq,5xs!KZyV"؍3i 7I)Ntn}syW6JN-"NPΙxmӻQǤS՘݂*us,JCxXEw2 Db_Վ<XN {pga}/lj0BkiTL|:N/Waulf}-"uG3[(\O,\J|0b\^,.l^ER#D,6 ht Td4`S{?>]/Ĩ;XZx|oN:ǘ[1;5ud}7:KiVFJ:a%VLɇc<cW}$os{Dj5m2wluK Đb9 2E{ZI=57dV!N@/A*^0,84ΔC ˉ%ő2qNe5J;ӵ- 3Be#ܷ番w*}HHaby,keSΡVpu'LA~;1u\쀎z7Z g7s#AjF)٘wځDMJ|L[]Ksd^nVSS(Ͷ  ,Ji2mrU"=C%pϑaX=Nԟzf?#)Tz_?ԭKחGkAgjg_S?n{Ur!CG w0-ζ2 O;G sBI\){vkYE*w`K'$l<YRϿq}L߼}K>E럈t)_7ܴb4i /_Mui2}E@sݱg=S jeuS`,9aY{s$AIV$zdy\*rUNY@qy_4vHo9e)mdNe(XBȌltK #8\fgm_#s#!܏SŃè>,JFlGDۗ@DmfR2-Ϯ&W3*gS0 .f5&χSDBcԝ9Sqɠ&0tTkI+8y:sy+tĀpJZwVIcż퍢EL(ů_zQun 4w]6S$ĩ t&pT#G^F'GA *cϳ{(sbMKal! OZ?^NsUj-֌UPԤE!TH~Z:u;e|K*eyrO:٭8�r)֟٦7[[wht >r>.\ꏣPwNz-ȎΖcc2H`+c5dң4`8@;Mg<(>,Ǫ;BDH@@p|V#m;,|H=Chy1J8M}}܁6'm#* NIԐA*{RXq2  I}$;"N0^~}}2<!@dKM\'AaY7687v. }uR𼼪jܸ<& cOͶKFҰLOY@Bd'W;O, i#89e_k9-v)RT<001)OZN\V.{-ִm2jEr ɐ5eO]{T]<HRbki,v&0~]>|tX(t`ittGdmp&;ȾL{9:CxO-gM 5%hiHIz`E]Oh<QP۳Bmi.Is:ׇxD侅ve]ˉhˋo٬ŅJEEA.R|DV\Nh{c( [2]vM@΅&s^g+m-@~L0K6 YVY8:&%v%iޛ!wpXhy VK+d nJiЍ=jaw&ENr{FҀCN:Wt vGCrgEmeJZkgk\sv[%bmD7)HFd_ GO͇*R#8֙=/"%~,uM/3f/MS#"Ua#u!p:,\ Tr.WH|Yoa7lh1AkD!ž*PvFj1sgt=7aRqpbk:<pW|Wٲ?M\kOs0:n'V7rNyʔx٨m{6/dzCY +Ksc<I랛f9Dz}XM?znw'8 LkCK<?k5N3B}zxt9N<!6(hp 2_gĖG"F$8/y▣Kx)o=P2GO޿L u0\7 \MO־mG +,'{E ";'$ \@K™rG;~E2VgYز,X ^Ca3tx&ϦW: +[g.j(}ړ ]U!lΤR-V{* )S Vm$:>-~%kq?ZM"2k _43P8Vudl3 *jѠd^ĝO G㪚o0y"8ɸ-4:sYjC =GP EAp'Fv-H#]9aqH(opP1q9|Rk|.3v|?>F,g_c hԏpرɣ<;L]`$EI/6OvUă _LSo!' Uo³0gZl\ gǏw8HMx.z1άw8l1�ckp@t쿢Fii7U?h%[Fq8)^yWZl@#X6>X1kp5nq^k*C|'.. W\l7IiaQycY<٪m?6:U˸/'hzy|xj&{Jf(RYu1 `5b]J ە}w6*lq{oFhe$)%;"fH4cL+#ϰoU];c]X~U<㗑B톴b{3$`r�1i=#lx^vuFVW(E܂!B('ZvI;mMVT&}*y\K!HDS5FL3D{+/0R!YFA&ռG)srz;\Q8)WŎj`Ū(.ߖanf\3vOӜHi*݅Z^,^o;U;5(:eYF+)<b+DӋΠ wrbH!_@ūo%f>(0VQ<zu:4;SGHI< R! 5Oׂqᖠ pWwpDѐT 7b?&`eYϖ ;RE+U皱-D^5toPs`3J2̋:q7.qmЏn1͔lp08v)"6 \79 R C#SU(?sMN+ v@j u@%xHY &v[&?]n0BQao*z>J !q^'3 dXP-a@^[f( cq"_k>a"w SI9v$r=-.nj!=W?(�,9B:'Ɩ!Q.�dA4Fd>V�UVHQ%iEh.<8m/B5ƛKO#Cp g3+Y[pOk)cQQAT' ixA t,sFJ[έo)wB4çԟp)B}X C&EJ'D̚* F"IVhSt7s ,b>Tbh޺B<)v֡ #R Tjd#T S%-jF7NAg? ÿt?*̍Wnߧ"eo I9Xk:s<(}g4PBǨng1Z-[.VUP^ӫR" tDTdNީ=^rYghےmū.Ox׶׆K%:-L�?|mɥ'Qy q /(X(_-4˻ۧђ/߼:aLDiDD& eÓ`tXT`}IX" 5~t{K/7_NԷPzJucrVQ0pDV~B"F3|>D놄D( n 3[ߓc jJ1Rke%lFP&t=`GvjCf2)GJi#tj}ieme1}e; xHC9ㄺthɉʧ 0﫮`Lj^on&єrgJ )8V1c`Q=Ԋ|Ki;c[$3ܺ%sVIc5~FAaÞ+ 0 I\f$FKy@i5A&ױG2IE{~2|D_2VnjMoFtqmx];C+xG(-^ڍ)ă{fPmp\o\8򸳠>nRb�Skʻf (r_jMFpXTCdv y_š{s $(KVCe U% eSMr }C~1]uQ꡾_`%B`?,# #dc֫r1^0_/G٩䋞n߳E~:n͡M \co'Pu{i* /"dh'>Kj5f)?�vE!%1.l~G5Uk< PT/ʥ;iODn񟬖6y8 NSZuШh'Mf[S6bӛԿ%=:*hXJw8>|W.ƣ sI-@~tLc-<6l@kgMd =ޫfFɬ2 V{pd4ɫTO(|G)H1YꢄqP=|4I FPn*v51tB[y[;K�)Fo_}L^�##h\/EOPB'0(fܰ#> khg� oi*\[tü!#{$|{`"M u뛏$\jO* T^(k+!<=:KwxIOM믢Z=A!TҎůHVJƅkhcTMpqaCZ+Ս`=[�/MѶ7.)zG:PzlluaM]#7cjç r-gϞEGazŔ>ߋ0egsDwDp=Wd jJ䥎%jhP4ј=eG\&lC ~b\'锪?Q}vma¿4ӹiؽhԲ9ZXLIbdG:Sv/r67}#vDQQLI+XzW/@󵒛"U&Dd!f1ץgfaR$#֕ieef3>%|AIMASj39\O7L`U Z.pN#너5(d5vTj-aAJq}X$uQGdK;5�۬\MȹhVLf7pb؏y09io&ZT^RL>k"6_khzZ! ;:ϴde΢8jKT.D ETZD'VJ>[Êzo!K.UJzNC i:{�G;98Վ?aע<KZG)| {Ϧv6%盤ߙ1f oɅDO+wI*,LXWز&.#`xi*2*qnk E|EGjlr$ނ}3Czvy!psȹ{0B?&{Yu|<dو^�$FWU윛Br+cc3Ocծ'+[ٵJ 0gz.+%PG†9FhzmO0v\ojͮNpΗb5m=m%\/[xԜ󼘔1ꦤM?;BPiO }pQd}IE|0&ߓ�;ȈѱeD3*>*?b񔗆CA.}vjJ-Ӣ-n^H83̾^߉O%5$w,іqp ^:12?´zpjSpI*wL+r*߉@!οj 6}tcW P_:L_2OqrwK;6O4:2vBr* |KP2R)P3ېU5w0j*Le"N2>PJwu`~a�p❂]LPAkw� ^&N9Y M-zdR%`y?{fT3x>z6b*'1팂3(.cUH9a+<yxcykYKTD^B�sRӨ endstream endobj 631 0 obj << /Type /ObjStm /N 100 /First 907 /Length 3451 /Filter /FlateDecode >> stream x[[oF}ׯ9:6MSMƂi[Yr$9M|Ë(٦vpDΜ9}(`6*&Y3 Άqj14ΞyꋁEEG& rHJCkL0Lz%ѰLkpLƀg ϣRL{`J?rRQL{$FI�0 ˴G:{<� L[F{ `0axNif0=W tN9f*^Ӻ h8<e%3: $64X4d LOt3n&!Lk7tH P:f.xԍe{Ac^xp5=Ax=YͰ8" ~|�-&�$+PJr@CSO Xj8`>F?`Y$=Q9C= K= O=@zYXx}:F` Y9 b(JwP;a P8LLLIeTHӝ X-S7IqH`#RA&(&iivHց{0Zɓ?`t:[2]Oߏl~^̏U|?;b%;6eY2Hȸ%ԙ w=eO0~ь쫛Ȥ}�ALX!;*f Y)3L#2HqCF M41dA(Tf!t~dZ qaBIxLIi7E`t�zG̑J\F> ~@<(CÃf` fBj` ܔm0Hi= k:zT�!!3Rt 7qSƀ m  A ܖ0Q PYJ� |Dkx $ڈL\HbAHl"V!B #NTg 1 R(Z i@"l2o$uHPQtACei ʚ6U:5 }D<^`(լɢF>V)|6D!>k <fxT=*Ra G4*8>Ta IA8 VhDq0b6<Uf<_IJ:}%tӖ-* ` ە(M>#HVU#eTGB$ʩJw)A@g$\7VJv=Ml,"(1c2Kx P CDUqHYQXU+=NTCJQU`)rH.+E֢svP)v_ckhk(g{f-^yo6]&�{d;XzlO_V^rk"o泳d=ƏOKvNgğab\0g,Dbv;?+K]?|w%J-w Pd>o9`6*K\Wu"hǷ<\s$-ϲ:Wj<SgL53x%RE0̫  {JscGs&< %$M١ T<LŃD 7P"#9M/$�$"<ϔXF r+"\=o q=Ĉ-� 2lCDZH{9^R#ỷq:3 R0#$$2 h+q"#fiP%ӛM^84N7.e`޼wR*BDJyR0ﺘq7GYHiK)+,= l~!:0z -pY貎>pzQЧ4$ؗ FN ʭ.+o%tژ{DXzҊ$lvݿnG6u j$_K3[zE_ wDqe˶QYEV9O3әo!<qhYXikjӑQT>׾>k}O(T$p6Uc4-@yntzvm}y5~=a3iSFRK2}tG֑eo-$)XIRG%I3UIlA8)9Ņ/uVҩ%RKXj$T*)5 RS$g-ɶs[ YwI[DO2>9 b66mՒbcȲ8.hm6~VRTb1%f]^|q\1,I$7(q˯Y*I i r=$oڡj׿7T E[K'l>Ye":l׻?fz6.f|96;$'備jSvGz1ҠSE8 Y1*]|U2ϞN/'].뷀:ۍx*Svw3R= ?_;+y~}Se1/|Oi>}˺=?MfS9/xB‹&5%-F9fWꏛb_=IXk>S _Nqoh:I Stv?b9eq~:)1ј`/q_L_ռ(SBټ,泯K!ʪCkca>}4^u}3ZR/U[ie6;J4'ؕXۚs(9=:<yY|C/#X l>NFX5cHu-p!xQv^_@u*~PUje]˻T- C??{bE"U /*}X#5Er[(]o`tՠ/:9_nr2y=ʦ[nf$u2Gȋ?=*s8ɧ"+NB[HO&Y߸-o9SeVo጖[KBM\\c.d;6=2kάmXYua%vsFh{.S=HPs _\^i+eZM Zm2۸ό.RjM%tD�a/WXJ|L&QumɱNv>ˀuvbA[n+SJBPUKK"rLZYԓrWTi$dMf~j2/*Ϳ(u[AZhXk XMHPXfju]ꄏEe8E]HK%(p5/}[k2~+7i&\sp])E\7iT/kl'>v&J= Mâk�MKr 0M(7ϔ endstream endobj 740 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Producer(pdfTeX-1.40.20)/Keywords() /CreationDate (D:20200408155746-04'00') /ModDate (D:20200408155746-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019) kpathsea version 6.3.1) >> endobj 677 0 obj << /Type /ObjStm /N 98 /First 870 /Length 3433 /Filter /FlateDecode >> stream xڝM<z\Yⳁ-\vNmSΨ$w_~A axARZL6l#ڶQWm3_ҍ~4_]ch6'm| knhOlg*8aB5M dh)b;βlg5BPY_h 9X[#4f;5ss<Z4J6R 4R7Rg4-+FZV$GAslx,ϭ;EjqcR[G `xZH1:_{E2aY'2+ss`0ƶ!!m!뙦%pX'~GdrY/#>&(^>ZUqGh$ⲍXiîhV q0p ? $gU<y$xE̤c!+oŎD0T<#$I9$O<tCW<j%x%4{QH>^hs(E<' '$ ċâx=Bs( x8CS(֤0;V!t+7?/}ocݽz/=>q͇ݻͿGr^Rr2WVj߿܂αp&\f$ú >(s\h/}s} WYq W~v5aԨuF|Χt}b; o_>\qcǟQ_Tcbo7~2Fh9SvӴnښ֥Z?jm՗^%_KV}rkk]xҹ'?5~-`3u_R澀] Kyn7v5.e Lj)% iM5Дv4sgrg;s56Lvlkm8ۙq6)g[lfΦ٤m9gr6zku8뙳q)g]gΪYu9grjjeY8˙q)gU,gβYesVÔ,pNvƘr.n]Z:_|$\х{kRv2tOsǚ~8 w8[W>p9nYϽkT| ׇex%>k_tGxF~0' ](@&ϧS>xL>ñ_['=1Ӳ9h8`&QA|Dݢm-D#f u?^G``ŀ?#!R`ꎊHFk |r? Ӵnax*K0LJXWl^$/ra,2=u,l(H-ښSwCe#r VәΟn|aߜ3m}-6p}d~U}:14]\yjU)`_ oa+n8"yKr#|8[4I*-Yt),"IfE {slt8ranۼFbza% V|?U̇,|hJjxO&Wtmq}Ц#(OW}t ?Ɗ{1؈Rinp5z <|TW'+,Q4(7%߰QXχ(x8Hwڠj*WEZBUu GCbrz} ULΧ&j޶*xTAցg# qx⡶PEW޼YZ'YrWX@XRrP�[mZ.T6fiFl]ઐ3Cff᜼euWgJC!S.qݵݴ RCMTvpeEȺqGж43n ]*<`Wg4;_oջe1?jXJ罩I8m11Ue\o늂] ` m@-Iԝ>JP-6]U1M+<ySF Ӎ5."[u(sx5t~W!8<w/*g>#2nwT=0V;<;ZA,S2IO#} QK8JLkFk鼳anPӵOȴŢE-i#jlDg6y 7CU4z B)lD5`Ku/w7. <>&ǧ$$$&m.RE]t2*˂*҉7k6UIxĂQKl2A !if$ff5k4gBҼ&hjI&ќ9 jҼ"j Yblff5k4gkRaZşkXr$Bs,(8FD=3 5ne_яrddIFfBQ%̖ UǨ JQb;�hZ�id]Fe9!A:g@:ӯ@ dV u_+YN+*j|%A+mˇyE=*pl댛Y6x5bG5$r["i vMI/)kErd[R^lm _{5ݑZҭ"٥_EKޕMVү#ѥ߮4<9rJeILFk&Ơu \Y_ZeuE*u#%:[4|/^G Jm 1 mhڬ"kUp Zy�JIuE8fV�mV Кm@mni�Ygڬ-hc@aP$`,ZZZ@K\@H JׂlV,f̂bY)ġ7>(b;O['oE8fUXSEv/*Bx:Zu(d&YA!<Od@6+(غFPʿ]YXov *;U6=h@rrնzYs@Кu#ڬNyP2;[l{5kh:fZEYdVkZ Z}x='v6VF`6{6~/l|`1}Oַ_sqxĴXhm,6X/c/ (5)._xjOM_S<R4;@S,wgl@gH')єA_|̧c'_[Q5 $nHDŗ:P܃(:dnB{fRT~lH'}7tnN+5WGáW_^k?}Mî endstream endobj 741 0 obj << /Type /XRef /Index [0 742] /Size 742 /W [1 3 1] /Root 739 0 R /Info 740 0 R /ID [<B5486C3CD9E8F3D8F1F4C05ADAD314B2> <B5486C3CD9E8F3D8F1F4C05ADAD314B2>] /Length 1694 /Filter /FlateDecode >> stream x׹]K;xc/n}_XD!=� 8ae ':UvޞUuI)RbTGi40*6m8 v4\ľ'p1,/6enV}p%n60.Vl$p-;"6i6l6d1)T,ng`4$>3%ϲ06bx]b& w3bOظ~8 [r[ex͉vy=-cp\,pRl[N Q1GgE p.e7rJe*\&+7܆;p}x�<'sx/7{�>g/V}frZ0##{U URL V^_JCL-| > 1AmWNOũ$k$ 5 tURױV}6VXhURLj b꼿wWUYUeuliO*ȨJD򪟁i_1PzT@8Hz:]I9M΀@W[nUXۅbx$q s*뭜2~+|RJ*TRJ*c {Ӊ@>W\rU*W\r r[0[K`), �̎ ׍t1Uq>87Dqnmpv9YKp0G= G^w:pu֝sp.EG>]p 圞- p ]x�~No/cxvA [x',8O 1|i1DfVqjb,WBmq69pMĘ.$ R\Ůja6ӏgV '%.͸%!Az_.!7V =p"5~oᷰZX-V/r2,.\. e_],O<gBh!B gU6k!e6?YBr\6FmY~c_+jͫhl46l46Mq6򚞦G̩7B˦BFhH5Rځ~MҔicEL[4'ʴEK"Z4\6.4M6BFh#njcXmo jcڔiQۨm6dDS-.p.M/8+F0~!,-q2X+`%u�s�!nʷ_vl療>$ih?p�C9^gk{ Уq'Ӡ/B`wCTx <81־ӟo<=^|h&>yU|^ݷ,^G;7EO ?X`NjIt'?+?X?X`=R2\x_j :hA6hMioul`׆x!zxW{?쁏A#<xhYr!X endstream endobj startxref 143345 %%EOF �����������������������������������������������������������������������������������������������������������������xml2/tests/�����������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�13642154746�012312� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/��������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�13643540352�014143� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/records.dtd���������������������������������������������������������������������0000644�0001762�0000144�00000000242�13631515545�016302� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!ENTITY author "foo bar"> <!ENTITY hoqc "&author; Quantitative Consultancy"> <!ELEMENT records (record+)> <!ELEMENT record (field1)> <!ELEMENT field1 (#PCDATA)> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-url.R����������������������������������������������������������������������0000644�0001762�0000144�00000004752�13631515545�016060� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("url") test_that("url_absolute", { expect_equal( url_absolute(c(".", "..", "/", "/x"), "http://hadley.nz/a/b/c/d"), c("http://hadley.nz/a/b/c/", "http://hadley.nz/a/b/", "http://hadley.nz/", "http://hadley.nz/x")) expect_error(url_absolute(c(".", "..", "/", "/x"), c("http://hadley.nz/a/b/c/d", "http://foo.bar")), "Base URL must be length 1") }) test_that("url_relative", { expect_equal( url_relative("http://hadley.nz/a/c", "http://hadley.nz"), "/a/c") # The behavior of libxml2 with relative paths was changed in # https://github.com/GNOME/libxml2/commit/b1f87c0e4376a993e682f59471e2c455a9179e22, # libxml2 release 2.9.9 if (libxml2_version() < "2.9.9") { expect_equal( url_relative("http://hadley.nz/a/c", "http://hadley.nz/"), "../a/c") } else { expect_equal( url_relative("http://hadley.nz/a/c", "http://hadley.nz/"), "a/c") } expect_equal( url_relative("http://hadley.nz/a/c", "http://hadley.nz/a/b"), "c") expect_equal( url_relative("http://hadley.nz/a/c", "http://hadley.nz/a/b/"), "../c") expect_error(url_relative("http://hadley.nz/a/c", c("http://hadley.nz/a/b/c/d", "http://foo.bar")), "Base URL must be length 1") }) test_that("url_parse", { expect_equal( url_parse("http://had.co.nz/"), data.frame(scheme = "http", server = "had.co.nz", port = NA_integer_, user = "", path = "/", query = "", fragment = "", stringsAsFactors = FALSE)) expect_equal( url_parse("http://had.co.nz:1234/"), data.frame(scheme = "http", server = "had.co.nz", port = 1234L, user = "", path = "/", query = "", fragment = "", stringsAsFactors = FALSE)) expect_equal( url_parse("http://had.co.nz:1234/?a=1&b=2"), data.frame(scheme = "http", server = "had.co.nz", port = 1234L, user = "", path = "/", query = "a=1&b=2", fragment = "", stringsAsFactors = FALSE)) expect_equal( url_parse("http://had.co.nz:1234/?a=1&b=2#def"), data.frame(scheme = "http", server = "had.co.nz", port = 1234L, user = "", path = "/", query = "a=1&b=2", fragment = "def", stringsAsFactors = FALSE)) }) test_that("url_escape", { expect_error(url_escape("a b c", reserved = c("a", "b")), "`reserved` must be character vector of length 1") expect_equal( url_escape("a b c"), "a%20b%20c") expect_equal( url_escape("a b c", " "), "a b c") expect_equal( url_unescape("a%20b%2fc"), "a b/c") expect_equal( url_unescape("%C2%B5"), "\u00B5") }) ����������������������xml2/tests/testthat/test-xml_text.R�����������������������������������������������������������������0000644�0001762�0000144�00000004075�13516067254�017121� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("xml_text") test_that("xml_text returns only text without markup", { x <- read_xml("<p>This is some text. This is <b>bold!</b></p>") expect_identical(xml_text(x), "This is some text. This is bold!") expect_identical(xml_text(xml_children(x)), "bold!") }) test_that("xml_text returns only text without markup", { x <- read_xml("<p>This is some text. This is <b>bold!</b></p>") expect_identical(xml_text(x), "This is some text. This is bold!") expect_identical(xml_text(xml_children(x)), "bold!") }) test_that("xml_text works properly with xml_nodeset objects", { x <- read_xml("<x>This is some text. <x>This is some nested text.</x></x>") expect_identical(xml_text(x), "This is some text. This is some nested text.") expect_identical(xml_text(xml_find_all(x, "//x")), c("This is some text. This is some nested text.", "This is some nested text.")) }) test_that("xml_text<- and xml_set_text work properly with xml_nodeset objects", { x <- read_xml("<x>This is some text. <x>This is some nested text.</x></x>") expect_identical(xml_text(x), "This is some text. This is some nested text.") xml_text(x) <- "test" expect_identical(xml_text(x), "testThis is some nested text.") xml_set_text(x, "test2") expect_identical(xml_text(x), "test2This is some nested text.") }) test_that("xml_text trims whitespace if requested, including non-breaking spaces", { x <- read_html("<p> Some text €  </p>") expect_identical(xml_text(x), " Some text \u20ac \u00a0") expect_identical(xml_text(x, trim = TRUE), "Some text \u20ac") }) test_that("xml_integer() returns an integer vector", { x <- read_xml("<plot><point x='1' y='2' /><point x='2' y='1' /></plot>") expect_identical(xml_integer(xml_find_all(x, "//@x")), c(1L, 2L)) }) test_that("xml_double() returns a numeric vector", { x <- read_xml("<earth><point latitude = '42.3466456' longitude = '-71.0390351' /><point latitude = '-36.8523378' longitude = '174.7691073' /></earth>") expect_identical(xml_double(xml_find_all(x, "//@latitude")), c(42.3466456, -36.8523378)) }) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-as_list.R������������������������������������������������������������������0000644�0001762�0000144�00000002752�13516067254�016713� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("as_list") list_xml <- function(x) as_list(read_xml(x)) test_that("empty elements become empty lists", { expect_equal(list_xml("<x></x>"), list(x = list())) expect_equal(list_xml("<x><y/></x>"), list(x = list(y = list()))) expect_equal(list_xml("<x><y><z/></y></x>"), list(x = list(y = list(z = list())))) }) test_that("text nodes become character vectors", { expect_equal(list_xml("<x>a</x>"), list(x = list("a"))) expect_equal(list_xml("<x><y>a</y></x>"), list(x = list(y = list("a")))) }) test_that("cdata nodes become character vectors", { expect_equal(list_xml("<x><![CDATA[<y/>]]></x>"), list(x = list("<y/>"))) }) test_that("xml attributes become R attibutes", { expect_equal(list_xml("<x a='1' b='2'></x>"), list(x = structure(list(), a = "1", b = "2"))) }) test_that("xml names are preserved when attributes exist", { expect_equal(list_xml("<x a='1' b='2'><y>3</y><z>4</z></x>"), list(x = structure(list(y = list('3'), z = list('4')), a = "1", b = "2"))) }) test_that("special attributes are escaped", { expect_equal(list_xml("<x a='1' b='2' names='esc'><y>3</y><z>4</z></x>"), list(x = structure(list(y = list('3'), z = list('4')), a = "1", b = "2", .names='esc'))) }) test_that("attributes in child nodes", { expect_equal(list_xml("<w aa = '0'><x a='1' b='2' names='esc'><y>3</y><z>4</z></x></w>"), list(w = structure(list(x = structure(list(y = list('3'), z = list('4')), a = "1", b = "2", .names='esc')), aa = "0"))) }) ����������������������xml2/tests/testthat/test-xml_serialize.R������������������������������������������������������������0000644�0001762�0000144�00000002364�13516067254�020123� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("xml_serialize") x <- read_xml("<a> <b><c>123</c></b> <b><c>456</c></b> </a>") test_that("xml_serialize and xml_unserialize work with xml_document input", { out <- xml_unserialize(xml_serialize(x, NULL)) expect_identical(as.character(x), as.character(out)) f <- tempfile() on.exit(unlink(f)) xml_serialize(x, f) expect_identical(as.character(xml_unserialize(f)), as.character(x)) }) test_that("xml_serialize and xml_unserialize work with xml_node input", { b <- xml_find_first(x, "//b") out <- xml_unserialize(xml_serialize(b, NULL)) expect_identical(as.character(b), as.character(out)) f <- tempfile() on.exit(unlink(f)) xml_serialize(b, f) expect_identical(as.character(xml_unserialize(f)), as.character(b)) }) test_that("xml_serialize and xml_unserialize work with xml_nodeset input", { b <- xml_find_all(x, "//b") out <- xml_unserialize(xml_serialize(b, NULL)) expect_identical(as.character(b), as.character(out)) f <- tempfile() on.exit(unlink(f)) xml_serialize(b, f) expect_identical(as.character(xml_unserialize(f)), as.character(b)) }) test_that("xml_unserialize throws an error if given a invalid object", { expect_error(xml_unserialize(serialize(1, NULL)), "Not a serialized xml2 object") }) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/ns-multiple-default.xml���������������������������������������������������������0000644�0001762�0000144�00000000157�13516067254�020567� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<root> <doc1 xmlns = "http://foo.com"><bar /></doc1> <doc2 xmlns = "http://bar.com"><bar /></doc2> </root> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-print.R��������������������������������������������������������������������0000644�0001762�0000144�00000001417�13516067254�016406� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("print") x <- read_html("lego.html.bz2") body <- xml_find_first(x, "//body") divs <- xml_find_all(body, ".//div")[1:10] quicklinks <- xml_find_first(body, "//div[contains(@div, 'quicklinks')]") test_that("print method is correct", { expect_output_file(print(x), "output/print-xml_document.txt", update = FALSE) body <- xml_find_first(x, "//body") expect_output_file(print(body), "output/print-xml_node.txt", update = FALSE) divs <- xml_find_all(body, ".//div")[1:10] expect_output_file(print(divs), "output/print-xml_nodeset.txt", update = FALSE) }) test_that("xml_structure is correct", { quicklinks <- xml_find_first(x, "//div[contains(@div, 'quicklinks')]") expect_output_file(html_structure(quicklinks), "output/html_structure.txt", update = FALSE) }) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-dtd.R����������������������������������������������������������������������0000644�0001762�0000144�00000002421�13516067254�016021� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("dtd") test_that("xml_dtd works", { r <- xml_new_root(xml_dtd(name = "html", external_id = "-//W3C//DTD XHTML 1.0 Transitional//EN", system_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")) expect_identical("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n", as.character(r)) no_name <- xml_new_root(xml_dtd(external_id = "-//W3C//DTD XHTML 1.0 Transitional//EN", system_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")) expect_identical("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n", as.character(no_name)) no_name_external_id <- xml_new_root(xml_dtd(system_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")) expect_identical("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE SYSTEM \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n", as.character(no_name_external_id)) no_name_external_id_internal_id <- xml_new_root(xml_dtd()) expect_identical("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE >\n", as.character(no_name_external_id_internal_id)) }) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-xml_name.R�����������������������������������������������������������������0000644�0001762�0000144�00000003162�13516067254�017051� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("xml_name") test_that("qualified names returned when ns given", { x <- read_xml("ns-multiple-default.xml") ns <- xml_ns(x) bars <- xml_children(xml_children(x)) expect_equal(xml_name(bars), c("bar", "bar")) expect_equal(xml_name(bars, ns), c("d1:bar", "d2:bar")) }) test_that("error if missing ns spec", { x <- read_xml("ns-multiple-default.xml") ns <- xml_ns(x)[1] bars <- xml_children(xml_children(x)) expect_error(xml_name(bars, ns), "Couldn't find prefix") }) test_that("xml_name<- modifies the name", { x <- read_xml("ns-multiple-default.xml") ns <- xml_ns(x) bars <- xml_children(xml_children(x)) bar <- bars[[1]] xml_name(bar) <- "foo" expect_equal(xml_name(bar), "foo") expect_equal(xml_name(bar, ns), "d1:foo") # ns is ignored xml_name(bar, ns) <- "bar" expect_equal(xml_name(bar), "bar") expect_equal(xml_name(bar, ns), "d1:bar") xml_name(bars) <- "foo" expect_equal(xml_name(bars), c("foo", "foo")) old_mss <- mss <- xml_missing() xml_name(mss) <- "foo" expect_identical(old_mss, mss) }) test_that("xml_set_name modifies the name", { x <- read_xml("ns-multiple-default.xml") ns <- xml_ns(x) bars <- xml_children(xml_children(x)) bar <- bars[[1]] xml_set_name(bar, "foo") expect_equal(xml_name(bar), "foo") expect_equal(xml_name(bar, ns), "d1:foo") # ns is ignored xml_set_name(bar, "bar", ns) expect_equal(xml_name(bar), "bar") expect_equal(xml_name(bar, ns), "d1:bar") xml_set_name(bars, "foo") expect_equal(xml_name(bars), c("foo", "foo")) old_mss <- mss <- xml_missing() xml_set_name(mss, "foo") expect_identical(old_mss, mss) }) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-xml_find.R�����������������������������������������������������������������0000644�0001762�0000144�00000011401�13631515545�017043� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("xml_find") # Find one --------------------------------------------------------------------- test_that("xml_find_first returns a missing object if no match", { x <- read_xml("<x><y/></x>") expect_equal(xml_find_first(x, ".//z"), xml_missing()) }) test_that("xml_find_first returns the first match if more than one match", { x <- read_xml("<x><y/><y/></x>") y <- xml_find_first(x, ".//y") expect_is(y, "xml_node") }) test_that("xml_find_first does not deduplicate identical results", { x <- read_xml("<x><y/><y/></x>") y <- xml_find_all(x, ".//y") z <- xml_find_first(y, "..") expect_is(z, "xml_nodeset") expect_equal(length(z), 2) }) # Find all --------------------------------------------------------------------- test_that("unqualified names don't look in default ns", { x <- read_xml("ns-multiple-default.xml") expect_equal(length(xml_find_all(x, "//bar")), 0) }) test_that("qualified names matches to namespace", { x <- read_xml("ns-multiple-default.xml") ns <- xml_ns(x) expect_equal(length(xml_find_all(x, "//d1:bar", ns)), 1) expect_equal(length(xml_find_all(x, "//d2:bar", ns)), 1) }) test_that("warning if unknown namespace", { x <- read_xml("<foo><bar /></foo>") maybe_error( expect_warning(xml_find_all(x, "//g:bar"), "Undefined namespace prefix"), "evaluation failed") }) test_that("no matches returns empty nodeset", { x <- read_xml("<foo><bar /></foo>") expect_equal(length(xml_find_all(x, "//baz")), 0) }) # Find num --------------------------------------------------------------------- test_that("xml_find_num errors with non numeric results", { x <- read_xml("<x><y/><y/></x>") expect_error(xml_find_num(x, "//z"), "result of type:.*xml_missing.*, not numeric") expect_error(xml_find_num(x, "//y"), "result of type:.*list.*, not numeric") expect_error(xml_find_num(x, "1=1"), "result of type:.*logical.*, not numeric") expect_error(xml_find_num(x, "string(5)"), "result of type:.*character.*, not numeric") }) test_that("xml_find_num returns a numeric result", { x <- read_xml("<x><y>1</y><y/></x>") expect_equal(xml_find_num(x, "1 div 0"), Inf) expect_equal(xml_find_num(x, "-1 div 0"), -Inf) expect_equal(xml_find_num(x, "0 div 0"), NaN) expect_equal(xml_find_num(x, "1 div floor(-0.1)"), -1) expect_equal(xml_find_num(x, "1 div floor(0)"), Inf) expect_equal(xml_find_num(x, "1 div floor(-0)"), -Inf) }) # Find chr --------------------------------------------------------------------- test_that("xml_find_chr errors with non character results", { x <- read_xml("<x><y/><y/></x>") expect_error(xml_find_chr(x, "//z"), "result of type:.*xml_missing.*, not character") expect_error(xml_find_chr(x, "//y"), "result of type:.*list.*, not character") expect_error(xml_find_chr(x, "1=1"), "result of type:.*logical.*, not character") expect_error(xml_find_chr(x, "1+1"), "result of type:.*numeric.*, not character") }) test_that("xml_find_chr returns a character result", { x <- read_xml("<x><y>1</y><y/></x>") expect_equal(xml_find_chr(x, "string(5)"), "5") expect_equal(xml_find_chr(x, "string(0.5)"), "0.5") expect_equal(xml_find_chr(x, "string(-0.5)"), "-0.5") expect_equal(xml_find_chr(x, "concat(\"titi\", \"toto\")"), "tititoto") expect_equal(xml_find_chr(x, "substring(\"12345\", 2, 3)"), "234") expect_equal(xml_find_chr(x, "substring(\"12345\", 2)"), "2345") expect_equal(xml_find_chr(x, "substring(\"12345\", -4)"), "12345") }) # Find lgl --------------------------------------------------------------------- test_that("xml_find_lgl errors with non logical results", { x <- read_xml("<x><y/><y/></x>") expect_error(xml_find_lgl(x, "//z"), "result of type:.*xml_missing.*, not logical") expect_error(xml_find_lgl(x, "//y"), "result of type:.*list.*, not logical") expect_error(xml_find_lgl(x, "string(5)"), "result of type:.*character.*, not logical") expect_error(xml_find_lgl(x, "1+1"), "result of type:.*numeric.*, not logical") }) test_that("xml_find_lgl returns a logical result", { x <- read_xml("<x><y>1</y><y/></x>") expect_equal(xml_find_lgl(x, "1=1"), TRUE) expect_equal(xml_find_lgl(x, "1!=1"), FALSE) expect_equal(xml_find_lgl(x, "true()=true()"), TRUE) expect_equal(xml_find_lgl(x, "true()=false()"), FALSE) expect_equal(xml_find_lgl(x, "'test'='test'"), TRUE) }) test_that("Searches with empty inputs retain type stability", { empty <- xml_nodeset() expect_equal(xml_find_num(empty, "1 div 0"), integer()) expect_equal(xml_find_chr(empty, "string(0.5)"), character()) expect_equal(xml_find_lgl(empty, "1=1"), logical()) }) test_that("Searches with entities work (#241)", { res <- read_xml(test_path("records.xml"), options = "DTDVALID") field1 <- xml_find_all(res, "//field1") expect_equal(xml_text(field1), "foo bar Quantitative Consultancy") }) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-namespaces.R���������������������������������������������������������������0000644�0001762�0000144�00000002632�13637645657�017406� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("Namespaces") # XML parsing tests ------------------------------------------------------------ test_that("multiple default namespaces given unique names", { ns <- unclass(xml_ns(read_xml("ns-multiple-default.xml"))) expect_equal(ns, c(d1 = "http://foo.com", d2 = "http://bar.com")) }) test_that("repeated prefixes given unique names", { ns <- unclass(xml_ns(read_xml("ns-multiple-prefix.xml"))) expect_equal(ns, c(b = "http://baz.com", b1 = "http://bar.com")) }) test_that("aliased prefixes retained", { ns <- unclass(xml_ns(read_xml("ns-multiple-aliases.xml"))) expect_equal(ns, c(b = "http://bar.com", c = "http://bar.com")) }) # Low-level character vector tests --------------------------------------------- test_that("unique prefix-url combo unchanged", { x <- c(blah = "http://blah.com", rah = "http://rah.com") expect_equal(.Call(unique_ns, x), x) }) test_that("all prefixs kept", { x <- c(blah = "http://blah.com", rah = "http://blah.com") expect_equal(names(.Call(unique_ns, x)), c("blah", "rah")) }) test_that("multiple default namespaces can be stripped", { x <- read_xml("ns-multiple-default.xml") ns <- unclass(xml_ns(x)) expect_equal(ns, c(d1 = "http://foo.com", d2 = "http://bar.com")) expect_equal(length(xml_find_all(x, "//bar")), 0) xml_ns_strip(x) ns <- unclass(xml_ns(x)) expect_equivalent(ns, character()) expect_equal(length(xml_find_all(x, "//bar")), 2) }) ������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-read-xml.R�����������������������������������������������������������������0000644�0001762�0000144�00000005475�13643423126�016766� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("read_xml") test_that("read_xml errors with an empty document", { expect_error(read_xml(character()), "Document is empty") tf <- tempfile() file.create(tf) on.exit(unlink(tf)) expect_error(read_xml(tf), "Document is empty") }) test_that("read_html correctly parses malformed document", { lego <- read_html("lego.html.bz2") expect_equal(length(xml_find_all(lego, ".//p")), 39) }) test_that("parse_options errors when given an invalid option", { expect_error(parse_options("INVALID", xml_parse_options()), "`options` 'INVALID' is not a valid option") expect_error(read_html("lego.html.bz2", options = "INVALID"), "`options` 'INVALID' is not a valid option") # Empty inputs returned as 0 expect_identical(0L, parse_options("", xml_parse_options())) expect_identical(0L, parse_options(NULL, xml_parse_options())) # Numerics returned as integers expect_identical(12L, parse_options(12L, xml_parse_options())) expect_identical(12L, parse_options(12, xml_parse_options())) # Multiple inputs summed expect_identical(3L, parse_options(c("RECOVER", "NOENT"), xml_parse_options())) }) test_that("read_html properly passes parser arguments", { skip_if_not(libxml2_version() >= "2.9.2") blanks <- read_html(xml2_example("cd_catalog.xml"), options = c("RECOVER", "NOERROR")) expect_equal(as_list(blanks)$html$body$catalog$cd[[1]], "\r\n ") no_blanks <- read_html(xml2_example("cd_catalog.xml"), options = c("RECOVER", "NOERROR", "NOBLANKS")) expect_equal(as_list(no_blanks)$html$body$catalog$cd[[1]], list("Empire Burlesque")) }) test_that("read_xml works with httr response objects", { skip_on_cran() skip_if_offline() skip_if_not_installed("httr") x <- read_xml(httr::GET("http://httpbin.org/xml")) expect_is(x, "xml_document") expect_equal(length(xml_find_all(x, "//slide")), 2) }) test_that("read_html works with httr response objects", { skip_on_cran() skip_if_offline() x <- read_html(httr::GET("http://httpbin.org/xml")) expect_is(x, "xml_document") expect_equal(length(xml_find_all(x, "//slide")), 2) }) test_that("read_xml and read_html fail for bad status codes", { skip_on_cran() skip_if_not_installed("httr") skip_if_offline() expect_error( read_xml(httr::GET("http://httpbin.org/status/404")), class = "http_404" ) expect_error( read_html(httr::GET("http://httpbin.org/status/404")), class = "http_404" ) }) test_that("read_html works with non-ASCII encodings", { tmp <- tempfile() on.exit(unlink(tmp)) writeLines("<html><body>\U2019</body></html>", tmp, useBytes = TRUE) res <- read_html(tmp, encoding = "UTF-8") expect_equal(as.character(res, options = ""), "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\U2019</body></html>\n") }) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-xml_nodeset.R��������������������������������������������������������������0000644�0001762�0000144�00000004172�13516067254�017574� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("xml_nodeset") test_that("methods work on empty nodesets", { x <- read_xml("<a><b/></a>") empty <- xml_find_all(x, "//c") expect_error(empty[[1]], "subscript out of bounds") expect_identical(empty[1], empty) test <- empty xml_attr(test, "test") <- 1 expect_identical(test, empty) xml_attrs(test) <- c("test" = 1) expect_identical(test, empty) xml_name(test) <- "test" expect_identical(test, empty) xml_text(test) <- "test" expect_identical(test, empty) expect_identical(as.character(empty), character(0)) expect_identical(as_list(empty), list()) expect_identical(nodeset_apply(empty, identical), empty) expect_output(print(empty), "\\{xml_nodeset \\(0\\)\\}") expect_output(tree_structure(empty), NA) xml_add_child(test, "test") expect_identical(test, empty) xml_add_sibling(test, "test") expect_identical(test, empty) expect_identical(xml_attr(empty, "test"), character()) expect_identical(xml_attrs(empty), list()) expect_identical(xml_double(empty), numeric()) expect_identical(xml_find_all(empty), empty) expect_identical(xml_find_chr(empty), character()) expect_identical(xml_find_first(empty), empty) expect_identical(xml_find_lgl(empty), logical()) expect_identical(xml_find_num(empty), numeric()) expect_identical(xml_integer(empty), integer()) expect_identical(xml_length(empty), 0L) expect_identical(xml_name(empty), character()) expect_identical(xml_ns(empty), character()) expect_identical(xml_parent(empty), empty) expect_identical(xml_path(empty), character()) xml_remove(test) expect_identical(test, empty) xml_replace(test) expect_identical(test, empty) xml_set_attr(test, "test", 1) expect_identical(test, empty) xml_set_attrs(test, c("test" = 1)) expect_identical(test, empty) xml_set_name(test, "test") expect_identical(test, empty) xml_set_text(test, "test") expect_identical(test, empty) expect_identical(xml_siblings(empty), empty) expect_output(xml_structure(empty), NA) expect_identical(xml_text(empty), character()) expect_identical(xml_type(empty), character()) expect_identical(xml_url(empty), character()) }) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/output/�������������������������������������������������������������������������0000755�0001762�0000144�00000000000�13631515545�015506� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/output/print-xml_document.txt���������������������������������������������������0000644�0001762�0000144�00000000405�13631515545�022076� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{html_document} <html xmlns:og="http://ogp.me/ns#" xmlns:fb="http://www.facebook.com/2008/fbml"> [1] <head>\n<script type="text/javascript">var ue_t0=window.ue_t0||+new Date( ... [2] <body id="styleguide-v2" class="fixed">\n<script>\n if (typeof uet == ... �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/output/html_structure.txt�������������������������������������������������������0000644�0001762�0000144�00000013677�13516067254�021352� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<div.aux-content-widget-3.links.subnav [div]> {text} <h3> {text} {text} <div#maindetails_quicklinks> {text} <div.split_0> {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} {text} <div.split_1> {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} {text} {text} <hr> <div#full_subnav> {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link.ghost [href]> {text} {text} {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link.ghost [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link.ghost [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link.ghost [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <h4> {text} {text} <ul.quicklinks> <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <li.subnav_item_main> {text} <a.link [href]> {text} {text} {text} <hr> {text} <div.show_more> <span.titlePageSprite.arrows.show> {text} {text} <div.show_less> <span.titlePageSprite.arrows.hide> {text} {text} �����������������������������������������������������������������xml2/tests/testthat/output/print-xml_nodeset.txt����������������������������������������������������0000644�0001762�0000144�00000001371�13516067254�021725� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{xml_nodeset (10)} [1] <div id="wrapper">\n <div id="root" class="redesign">\n<scrip ... [2] <div id="root" class="redesign">\n<script>\n if (typeof uet == 'funct ... [3] <div id="nb20" class="navbarSprite">\n<div id="supertab">\t\n\t<!-- begi ... [4] <div id="supertab">\t\n\t<!-- begin TOP_AD -->\n<div id="top_ad_wrapper" ... [5] <div id="top_ad_wrapper" class="dfp_slot">\n<script type="text/javascrip ... [6] <div id="top_ad_reflow_helper"></div> [7] <div id="navbar" class="navbarSprite">\n<noscript>\n <link rel="stylesh ... [8] <div id="nb_search">\n <noscript><div id="more_if_no_javascript"><a h ... [9] <div id="more_if_no_javascript"><a href="/search/">More</a></div> [10] <div class="magnifyingglass navbarSprite"></div> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/output/print-xml_node.txt�������������������������������������������������������0000644�0001762�0000144�00000002334�13631515545�021210� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{html_node} <body id="styleguide-v2" class="fixed"> [1] <script>\n if (typeof uet == 'function') {\n uet("bb");\n }\n ... [2] <script>\n if ('csm' in window) {\n csm.measure('csm_body_delive ... [3] <div id="wrapper">\n <div id="root" class="redesign">\n<scrip ... [4] <script type="text/javascript" src="http://ia.media-imdb.com/images/G/01 ... [5] <script type="text/imdblogin-js" id="login">\njQuery(document).ready(fun ... [6] <script type="text/javascript">\n jQuery(\n ... [7] <iframe id="sis_pixel_sitewide" width="1" height="1" frameborder="0" mar ... [8] <script>\n setTimeout(function(){\n try{\n //sis3.0 ... [9] <script type="text/javascript" src="http://ia.media-imdb.com/images/G/01 ... [10] <script type="text/javascript">\nif(window.COMSCORE){\nCOMSCORE.beacon({ ... [11] <noscript>\n<img src="http://b.scorecardresearch.com/p?c1=2&c2=60349 ... [12] <script>\n doWithAds(function(){\n (new Image()).src = "http:/ ... [13] <script>\n(function(){\n var readyTimeout = setInterval(function(){\n ... [14] <div id="servertime" time="235"></div> [15] <script>\n if (typeof uet == 'function') {\n uet("be");\n }\n ... ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-comment.R������������������������������������������������������������������0000644�0001762�0000144�00000000402�13516067254�016705� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("comment") test_that("Comment creation works", { x <- xml_new_root("root") xml_add_child(x, xml_comment("Hello!")) expect_identical("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root><!--Hello!--></root>\n", as.character(x, options = "")) }) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/ns-multiple-aliases.xml���������������������������������������������������������0000644�0001762�0000144�00000000163�13516067254�020561� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<root> <doc1 xmlns:b="http://bar.com"><b:bar /></doc1> <doc2 xmlns:c="http://bar.com"><c:bar /></doc2> </root> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-xml_parse.R����������������������������������������������������������������0000644�0001762�0000144�00000000402�13631515545�017234� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������test_that("download_xml fails if curl is not installed", { mockery::stub(download_xml, "requireNamespace", function(...) FALSE) expect_error( download_xml("http://httpbin.org/xml"), "`curl` must be installed to use `download_xml\\(\\)`" ) }) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/records.xml���������������������������������������������������������������������0000644�0001762�0000144�00000000217�13631515545�016331� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE records SYSTEM "records.dtd"> <records> <record> <field1>&hoqc;</field1> </record> </records> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/ns-multiple.xml�����������������������������������������������������������������0000644�0001762�0000144�00000000207�13516067254�017141� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<root xmlns:f="http://foo.com" xmlns:g = "http://bar.com"> <doc1><f:bar f:id="a" /></doc1> <doc2><g:bar g:id="b" /></doc2> </root> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-cdata.R��������������������������������������������������������������������0000644�0001762�0000144�00000000357�13516067254�016330� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("cdata") test_that("CDATA creation works", { x <- xml_new_root("root") xml_add_child(x, xml_cdata("<d/>")) expect_identical(as.character(x), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root><![CDATA[<d/>]]></root>\n") }) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-as_xml_document.R����������������������������������������������������������0000644�0001762�0000144�00000002335�13631521044�020421� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("as_xml_document") roundtrip_xml <- function(x) { xml <- read_xml(x) lst <- as_list(xml) xml2 <- as_xml_document(lst) expect_equal(as.character(xml), as.character(xml2)) } test_that("roundtrips with single children", { roundtrip_xml("<a><b/></a>") roundtrip_xml("<a><b><c/></b></a>") roundtrip_xml("<a><b>foo<c/></b></a>") roundtrip_xml("<a><b>foo<c>bar</c></b></a>") roundtrip_xml("<a x = '1'><b y = '2'>foo<c z = '3'>bar</c></b></a>") }) test_that("roundtrips with multi children", { roundtrip_xml("<a><b1/><b2/></a>") roundtrip_xml("<a><b><c1/><c2/></b></a>") roundtrip_xml("<a><b1>foo<c/></b1><b2>bar<c/></b2></a>") roundtrip_xml("<a><b>foo<c>bar</c><c>baz</c></b></a>") roundtrip_xml("<a x = '1'><b y = '2'>foo<c z = '3'>bar</c></b></a>") roundtrip_xml("<a x = '1'><b y = '2'>foo<c z = '3'>bar</c></b><c zz = '4'>baz</c></a>") }) test_that("rountrips with special attributes", { roundtrip_xml("<a names = 'test'><b/></a>") }) test_that("more than one root node is an error", { expect_error(as_xml_document(list(a = list(), b = list())), "Root nodes must be of length 1") }) test_that("Can convert nodes with leading and trailing text", { roundtrip_xml("<a>foo<b>bar</b>baz</a>") }) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-null.R���������������������������������������������������������������������0000644�0001762�0000144�00000005063�13516067254�016225� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("Null XPtr") data <- read_xml("ns-multiple.xml") tf <- tempfile() on.exit(unlink(tf)) saveRDS(data, file = tf) x <- readRDS(tf) test_that("accessors all fail rather than crash with NULL Xptrs", { expect_error(as_list(x), "external pointer is not valid") expect_error(html_structure(x), "external pointer is not valid") expect_error(xml_add_child(x, x), "external pointer is not valid") expect_error(xml_add_sibling(x, x), "external pointer is not valid") expect_error(xml_attr(x, "foo"), "external pointer is not valid") expect_error(xml_attr(x, "foo") <- "bar", "external pointer is not valid") expect_error(xml_attrs(x), "external pointer is not valid") expect_error(xml_attrs(x) <- list(), "external pointer is not valid") expect_error(xml_child(x), "external pointer is not valid") expect_error(xml_children(x), "external pointer is not valid") expect_error(xml_contents(x), "external pointer is not valid") expect_error(xml_double(x), "external pointer is not valid") expect_error(xml_find_all(x, ""), "external pointer is not valid") expect_error(xml_find_chr(x, ""), "external pointer is not valid") expect_error(xml_find_first(x, ""), "external pointer is not valid") expect_error(xml_find_lgl(x, ""), "external pointer is not valid") expect_error(xml_find_num(x, ""), "external pointer is not valid") expect_error(xml_has_attr(x, ""), "external pointer is not valid") expect_error(xml_integer(x), "external pointer is not valid") expect_error(xml_length(x), "external pointer is not valid") expect_error(xml_name(x), "external pointer is not valid") expect_error(xml_name(x) <- "foo", "external pointer is not valid") expect_error(xml_ns(x), "external pointer is not valid") expect_error(xml_ns_strip(x), "external pointer is not valid") expect_error(xml_parent(x), "external pointer is not valid") expect_error(xml_parents(x), "external pointer is not valid") expect_error(xml_path(x), "external pointer is not valid") expect_error(xml_remove(x), "external pointer is not valid") expect_error(xml_replace(x, x), "external pointer is not valid") expect_error(xml_set_namespace(x, "foo"), "external pointer is not valid") expect_error(xml_siblings(x), "external pointer is not valid") expect_error(xml_structure(x), "external pointer is not valid") expect_error(xml_text(x), "external pointer is not valid") expect_error(xml_text(x) <- "test", "external pointer is not valid") expect_error(xml_type(x), "external pointer is not valid") expect_error(xml_url(x), "external pointer is not valid") }) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/helper-version.R����������������������������������������������������������������0000644�0001762�0000144�00000000115�13631515545�017230� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cat("This is libxml2 version", as.character(xml2:::libxml2_version()), "\n") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-xml_schema.R���������������������������������������������������������������0000644�0001762�0000144�00000001403�13516067254�017365� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("xml_schema") test_that("xml schema validates", { doc <- read_xml(system.file("extdata/order-doc.xml", package = "xml2")) schema <- read_xml(system.file("extdata/order-schema.xml", package = "xml2")) expect_true(xml_validate(doc, schema)) }) test_that("xml schema errors", { str <- readLines(system.file("extdata/order-doc.xml", package = "xml2")) str <- sub("<quantity>1", "<quantity>", str) str <- sub("95819", "ABC95819", str) str <- sub('partNum="926-AA"', "", str) doc <- read_xml(paste(str, collapse = "\n")) schema <- read_xml(system.file("extdata/order-schema.xml", package = "xml2")) out <- xml_validate(doc, schema) expect_false(out) errors <- attr(out, "errors") expect_is(errors, "character") expect_length(errors, 4) }) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/test-write_xml.R����������������������������������������������������������������0000644�0001762�0000144�00000007172�13516067254�017270� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("write_xml") test_that("write_xml errors for incorrect directory and with invalid inputs", { x <- read_xml("<x/>") filename <- ".../test.xml" expect_error(write_xml(x, filename), "'...' does not exist in current working directory") expect_error(write_xml(x, c("test.xml", "foo")), "`file` must be a non-zero character of length 1") }) test_that("write_xml works with relative file paths", { x <- read_xml("<x/>") filename <- "../test.xml" on.exit(unlink(filename)) write_xml(x, filename, options = "no_declaration") expect_identical(readChar(filename, 1000L), "<x/>\n") }) test_that("write_xml works with no options", { x <- read_xml("<x/>") filename <- "../test.xml" on.exit(unlink(filename)) write_xml(x, filename, options = NULL) expect_identical(readChar(filename, 1000L), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<x/>\n") }) test_that("write_xml works with an explicit connections", { x <- read_xml("<x/>") filename <- "../test.xml" file <- file(filename, "wb") on.exit(unlink(filename)) write_xml(x, file, options = "no_declaration") close(file) expect_identical(readChar(filename, 1000L), "<x/>\n") }) test_that("write_xml works with an implicit connections", { x <- read_xml("<x/>") filename <- "../test.xml.gz" write_xml(x, filename, options = "no_declaration") file <- gzfile(filename, "rb") on.exit({unlink(filename); close(file)}) expect_identical(readChar(file, 1000L), "<x/>\n") }) test_that("write_xml works with nodeset input and files", { x <- read_xml("<x><y/><y><z/></y></x>") y <- xml_find_all(x, "//y") filename <- "../test.xml" on.exit(unlink(filename)) expect_error(write_xml(y, filename, options = "no_declaration"), "Can only save length 1 node sets") write_xml(y[1], filename, options = "no_declaration") expect_identical(readChar(filename, 1000L), "<y/>") }) test_that("write_xml works with nodeset input and connections", { x <- read_xml("<x><y/><y/></x>") y <- xml_find_all(x, "//y") filename <- "../test.xml.gz" expect_error(write_xml(y, filename, options = "no_declaration"), "Can only save length 1 node sets") expect_error(write_xml(y[1], c(filename, "foo")), "`file` must be a non-zero character of length 1") write_xml(y[1], filename, options = "no_declaration") file <- gzfile(filename, "rb") on.exit({unlink(filename); close(file)}) expect_identical(readChar(file, 1000L), "<y/>") }) test_that("write_xml works with node input and files", { x <- read_xml("<x><y/><y/></x>") y <- xml_find_first(x, "//y") filename <- "../test.xml" expect_error(write_xml(y, c(filename, "foo")), "`file` must be a non-zero character of length 1") write_xml(y, filename, options = "no_declaration") on.exit(unlink(filename)) expect_identical(readChar(filename, 1000L), "<y/>") }) test_that("write_xml works with node input and connections", { x <- read_xml("<x><y/><y/></x>") y <- xml_find_first(x, "//y") filename <- "../test.xml.gz" write_xml(y, filename, options = "no_declaration") file <- gzfile(filename, "rb") on.exit({unlink(filename); close(file)}) expect_identical(readChar(file, 1000L), "<y/>") }) test_that("write_html work with html input", { x <- read_html("<html><title>Foo") filename <- "../test.html.gz" write_html(x, filename) file <- gzfile(filename, "rb") on.exit({unlink(filename); close(file)}) expect_identical(readChar(file, 1000L), "\n\n\nFoo\n\n") }) xml2/tests/testthat/test-format.R0000644000176200001440000000121313516067254016534 0ustar liggesuserscontext("format") test_that("format.xml_node prints attributes for root nodes", { x <- read_xml("") expect_equal(format(x), "") }) test_that("format.xml_node prints namespaces for root nodes", { x <- read_xml("") expect_equal(format(x), "") y <- read_xml("") expect_equal(format(y), "") z <- read_xml("") expect_equal(format(z), "") }) xml2/tests/testthat/helper.R0000644000176200001440000000015013516067254015545 0ustar liggesusersmaybe_error <- function(code, ...) { tryCatch(code, error = function(e) expect_error(stop(e), ...)) } xml2/tests/testthat/ns-multiple-prefix.xml0000644000176200001440000000016313516067254020435 0ustar liggesusers xml2/tests/testthat/test-xml_missing.R0000644000176200001440000000310413516067254017576 0ustar liggesuserscontext("xml_missing") x <- read_xml("

Some text.

Some other.

No bold text

") para <- xml_find_all(x, ".//p") b <- xml_find_first(para, ".//b") mss <- b[[3]] test_that("xml_find returns nodes of class 'xml_missing' for missing nodes", { expect_equal(length(b), 3L) expect_equal(vapply(b, length, integer(1)), c(2L, 2L, 0L)) expect_is(mss, "xml_missing") }) test_that("xml_missing methods return properly for all S3 methods", { expect_equal(as.character(mss), NA_character_) expect_equal(as_list(mss), list()) expect_equal(nodeset_apply(mss), xml_nodeset()) expect_output(print(mss), "\\{xml_missing\\}\n") expect_equal(tree_structure(mss), NA_character_) expect_error(write_xml(mss), "Missing data cannot be written") expect_error(write_html(mss), "Missing data cannot be written") expect_equal(xml_attr(mss), NA_character_) expect_equal(xml_attrs(mss), NA_character_) expect_equal(xml_find_all(mss), xml_nodeset()) expect_equal(xml_find_chr(mss), character()) expect_equal(xml_find_lgl(mss), logical()) expect_equal(xml_find_num(mss), numeric()) expect_equal(xml_find_first(mss), xml_missing()) expect_equal(xml_length(mss), 0L) expect_equal(xml_name(mss), NA_character_) expect_equal(xml_parent(mss), xml_missing()) expect_equal(xml_path(mss), NA_character_) expect_equal(xml_text(mss), NA_character_) expect_equal(xml_type(mss), NA_character_) expect_equal(xml_url(mss), NA_character_) }) test_that("is.na() should return TRUE for xml_missing", expect_true(is.na(xml_missing())) ) xml2/tests/testthat/test-xml_children.R0000644000176200001440000000301713516067254017720 0ustar liggesuserscontext("xml_children") x <- read_xml(" ") test_that("xml_child() returns the proper child", { expect_identical(xml_child(x), xml_children(x)[[1L]]) expect_identical(xml_child(x, 2), xml_children(x)[[2L]]) }) test_that("xml_child() returns child by name", { expect_identical(xml_child(x, "baz"), xml_find_first(x, "./baz")) }) test_that("xml_child() errors if more than one search is given", { expect_error(xml_child(x, 1:2), "`search` must be of length 1") }) test_that("xml_child() errors if search is not numeric or character", { expect_error(xml_child(x, TRUE), "`search` must be `numeric` or `character`") expect_error(xml_child(x, as.factor("test")), "`search` must be `numeric` or `character`") expect_error(xml_child(x, raw(1)), "`search` must be `numeric` or `character`") expect_error(xml_child(x, list(1)), "`search` must be `numeric` or `character`") }) test_that("xml_length", { expect_equal(xml_length(x), 2) all <- xml_find_all(x, "//*") expect_equal(xml_length(all), c(2, 1, 0, 0)) }) test_that("xml_parent", { expect_identical(unclass(xml_parent(xml_child(x))), unclass(x)) }) test_that("xml_parents", { expect_equal( xml_name(xml_parents(xml_find_first(x, "//boo"))), c("bar", "foo")) }) test_that("xml_root", { doc <- xml_new_document() expect_is(xml_root(doc), "xml_missing") a <- xml_add_child(doc, "a") b <- xml_add_child(doc, "b") expect_that(xml_name(xml_root(b)), equals("a")) expect_that(xml_name(xml_root(doc)), equals("a")) }) xml2/tests/testthat/lego.html.bz20000644000176200001440000012323113516067254016461 0ustar liggesusersBZh91AY&SY~7u@@`ymۚ[cEFϽk继hyn rttu [lO(}z:}MʋX^ Z;}7޾޶kΩwoSn.i@zaxnŌjX;mͽwۺ>}j:wvvî*VGUsIK޾u_M 6ק|W};n;u5mlzݵwcr{o9rz۽}<G]SRo]er-{ݺgvͽwzz羺.Vu={ͻU}w{7n=k>9Wݻ۝^ޕNon9mgt=7Qk[\,/M;ת{}4ոy}fq^:gZ};}i=d}/v d@e4G4@&@& 44hBi6Q@ 40<'4c"M#4i&j4hd&B & 4hjzI=OI鉩 @$Dm&M5=SɣFM4ST&hDM hi !%=O)=M445x EQ j?*X#/H ( ̇`B;Jp? K1O8MĀ d*~@*a5Xq55m6eo& l(:ROSB&;0쭄tAME6L{٤5ڐ"X]N/PII}w[kQ 41Ь1(j9!O P7J0 24,:Bk.` Yzl2 D1r.(A=ЗlL}-Z˕MNDL j @(uk˱3SX1ZH1Ciƌl b@;Hw31k8ȲE+mffcid03ޗiQN 2 9_o_X"reE" ?ɻdb$(_X% WYj[DȕiX,•h@_ f>~J iJ + ͸1%0ԁqXjCȶTƚBy`"8S/@@ ֕"e0`((MM&BhNb$Hn12R IBF6*w@Mb^$đPTFRaqT/gH ~@2IdAQ5T" GBKlRB"0uaXUE @IdE"BsR@*Z{%A`!BESyƚ|&j1AUL;"%CxdBhaą..)[1 n?]g?cMa-@z){F4g~!L=Z/tE·7Na$ bgy9<9 \7&<1stqM*B1cEF*DVH"YNu'"_fa8>,Gc՞#^#'k;w[|( a>35+;%޹ɬ U'9%q`xr5o= F=dT@PjVY -L/٦'CCC1W]Ozfq>D.6xfɹ^'肜(pGwP!hN :}!|T5U~ps"u~|M#aw0A3EE*Y 1ߨsbi{sgr,]qLxiD=-o©՜)Ӽ³u>R#٩Ǐf8csZgpZڳ lʣ[JosfrBQp7Fjlcr9q#_[靃d!'^~o/{u%nU:&GAhD!'],.{-7-4^G@:v=Fy/&CeɊeNMJ aϫe*+El0bM= ykUbaT Ik#|ś0*rgmT@+3{ܻ3&zK Z5m$ٸLJ4d{܃Wo cYklvs/΁5Y v;G\ۙŚ/G 7 r26=5̝>Ee\ZK:i;\,sR↮Z!jbOL{rn n /Ui|rɝP;52BJx,ؠ1BJl"'#CH$8B\F f "]Jƛ,vu(AD qG\F A@&ɳd$2BTI ! vǬT?b[*zVJ;ԗZdöjb@F$ZlEXwm TǚꟖ< -F.V3oT3zv!cS5F;{u}-ܻ*vݲE<=ȅ!. "Qh 3n z7B@sStǩT rn@h4_2h&h޸Ӱl+> 'lB=>i9=U!-S\(EY5ĝ*bM\1؏#ffը~1-l+TtI =<;ngn`j\/ִҴ3QV#;_P+ޢ6oHW8 3q"0 Ea|mcѧ`:n:Vbt CT@ ZD^(2yd6LsH*Vi ~`*+rJ_<[bڷ$F$1{>S]֮^^z .i,lu<4ڜG3TJE<JЙ}oWa2iTMW3SH:3=MD &xߛEݻ@hzp3#i_J67fr шwsp@P]G=㝊%=vr[4 <ی:{ۍpP 7{)ަkp_]NOg>|3k3x4vNJknKDavVE0\I<15!*o5۝cNV9/_K(m.:o ɴvzVS5=Ejtu| };̈́6/|f83|z\rErx Xqcԅ7c>|NQ%oGt2f8cW [K0#;33e6~Zd*2$s,? hS~!הюD1ct-N[3%U<28ru~y~pYq@2Q ̴j]mFC=mVw]c1 u߿{2/Q܍%?/Gh(;?`$Yy|jX~^s3ׇ|OQ=P;>-[Jv<㻎;yS7< v$3.TQ;4!Md* !s<\e ` 9#1ԔKB"{a| ^!p0;7pn`IaΣL٫|[rlb4]{!iA"Nwi7M[6As)g磋_z'E{_%Xn\PdY (%Ye6"HRZte‹B_\s Sے b)zR@TݤRc|'ɼ.|d{N˭X4P{C#6M&f+8uW%+GyyT32fLJNG޷E(6"JHl5`A$ rfUuTmkU r&g_.nWvbbmps2 %-HҪV"(d>/x2ol%$7w>YB]0StDডq#Ha7/dtj! *߷b ]ź) apQ4mP *p*7΍6J4 jUMe冞'/MB:Xjıw7sm?dqęLp=6@G鈵6Pm>;zp5a Ir'ʋ4@2J@ K#PCX#\ X 3 Nځ6BB Ba&" 4 1 ^=`K!WfBJa)""VHP"B! $c7Hi% (IA8vWc]9~&b&lwbn{m)h T q-KơPRk pBWp [ʽu5ux( n^|.sH^(6{'[{9wHa`Y\͟_l_ڮ hSx@zq˷]slgbW:ўvPcCfӓef MeM]]'$jOM(y&=#;} &m 7AQ^38 FsZSܛ lAXҺBnscVy~gB t9!"ImM["ş66 1 ;;۞-2Opta/H.y.J2NYb3u K$%-KQ`;]C6`nY<(ow2 V{Rqg\wϥ>V1Xޠt&hgS/.)_U,Cn{兕s3!ÙhЉԮP:1 uF2ALIocr ۻKy^ fV4uqY|so+[%5-uI'oq&wqgJ$| 6&/F_]X|y>߻XLBQcl9ǧLā=\ "͜ߥeg:awbKGݽ! AwR C?.}4V&Ik(qa]pGwLr"0=6 0mV_0z>ܳމ32DU踣'4n7ms&9y3فx n8͈ONNBb'ߌw}=8ah<|/}*B>P`ـ-p>?M;t:ݯ$=xKtoKe ?HTȚ hbM b<|}ym^3+9ƍ㘦PՇ!Lo1B.8~:!<EH'RV I,+Ec+t't`_X:9b9FNlkR1h-#3O& meg 5d3e5MmY 3xE3AUM3oyf$ 8>uHdJ+%(@d9 1a{~bfjUbLP@XudyGemc3 ֙ 3ZAuR kECErk\F_#`qw~G+J{Dzx8u](UG81<|P @m(VVµ~ȝc86`qQӽF%d|a~",yiI0 [\}z {k yIXC:K1g 19ma֮V/.F/4H$ sW?|AXGP1N-y>q( cYc)O3Npa jH-Ԣ<_um)I DWiIVlOa.#:$qAd&E e3B*|t&@qf–,)J _y$dX4#//z|"!V y60t(DeF -h 4rBp1SD #Fu \+}Ԇ|:q7 XGx(S BY5sJP&kNB{eh&`<$L^}~?*$9Ɗi; Z(R'j%eHVO:]׷ S q qMo.wu@k a0p,CTA*@xN3tk؁:vп]dՁ`Hacxv!$5 hK!_wp(GML%ߖl& {{ c!GSd& 殣 @~س 39CaMu4Dbu<#욚wzKɧ6S0g s)@?ѝG`*>|Btv:׳䞲O;-*92nVh$ڮ@ǖ?Dj@(#жwS9/%x55vgnAw}Js+vs\P d&v",ƚW rs_WzP?RD DFC~ͦ6a fWc",!`[q$Ad0"d\‰6ID.7 n޲E)uZIFg.6x~L)ig{Xbmh1L VFqfup7@4 LF­ .l.#g$#TKjO4$e!oA%\:Y5)as.Xu" ӳd]P_u})V,#a\**2ѠH_;a(`ThBe) b+6bz`MVb4.FV!2ߙ1MSOĝNE&̈́ yD!;EU\Gg+G),?۽bs)Fۥ1)ׁIB섩BqڎF\Znb_A%j##ZUyȬوՔOW55A+`):OU!9A]rx-DAi20`FWUP'c7fjK;/o*lNH"|ʞW%5_3ϫU.8Qۈ޳N'b'ۜU tBp;L7xYW>N %mPJ7^s:IIB Ę"f{4HYl/W82=%G.+z{}&U}`1Rj" VhgˆeQ8OcIq+qOܠrٟFYq.qRH҃uoK=Dq;FJgXfN:0UXiɆdJoj=%fF|50ޙz3$d AǏ3A8w^s쬊ۿ ͨZF۩V^KpjfKP Xp ~ódէy=4u{"`d*'n /كyE<`÷Ǎ%Fɠ nh,)+SSJuN̊M0w'ն2_` ĩB&o<a )3-ӵ]Ͽ_AtWn!|_J{<jL =}^u[eჰ}U_E\-o[roL.?ȃ4V8/.CcMC cmI_?@6;liݓԁhթ8k8ufH4Yum#}=XYYJme.1n @Ip4T/'EƫP4$>|(/`ax*{sυ'ǐส1+HR)Yp*Wvp2AiՒ0O=<%Z7lҏ魰"~p@Ŵyaz *6֮>Y|`VA$IX{K z=-.ˬU9Ab+9z>Јw2$Euٴ}=ozOmKye{ .ZT#́l@Ձ!/ dz?CoN'q} ىB i^ &`\4sBh׾;_@~ نnDd؀H0#ΨMAf* ~ɘEy]]ZJ'p8-AX$'Uh+.JOmNȂATBz* ߘ!WgUJ0!17[1ϏB'>;uvSUUA’,꼀VC>#9;~SD8.d"!?dWf^Z&S yi>(גKUu:O%aF 8PC{%My>>#́5~$Gdhu%ѯ%´_.GrI٦| _0K1RAK3TYRA;\ ֒r\ 8rF2kexl/8YE2(88'%MEBjUɡGVv7<\^n&y%90ùs@%z#q ` \-9J:桭ՕJ'Jc;C?${2] 'O~`~E|wA -bO23sϯQ52"vQ W 0^J?~V ~/a';l[;X{ФL_:L3dvgH1/ c ˏL>ϴOM︉Xq0Sw uH/9BʾX4Bz_';{!yN₍$ܦ<黡[H _/"W#1pfޢ).IZO/6&o"r%qpl.Rl GeOk9x[OWL2w[/Sdއ9Ju;̂lUn[`[J Vc!;)džjwɕJ]m-=-8: zZw/|*V2E 束/ea*>Ih%>L|jK䃷y2:3$0h65d3 $?&hoFCMq|wκ>5o<6>7r Ae9KPE@3QV >Kzn6`fJ>U<ŵn˰.;Lh(N[YE~@/"M4(+aFE"=L;*‡$`Sno$8)fVnbk慞>$*L %>F+ƩblJcxefg&r~ (4> zuA6M}4Yn՚!*ZH.6Rr sgY !#Ì07bO+co$Qj9 #2t0t6ɋ$N1/Ev9ޫ U&rOٙ%P-hZ+ȚɾwM59Q@ #xLILU SH$2f_q^ZZ0ѯ}E 54BF`Y"0e`6W:J bM=/[)٫ؕ,Wϫ;Ց8͟7CvI8I| ?W<%؜ >1h͚ iئٙd ƌT~HU q`f:hwd~[@5װ+Y[`7uj^o)`J?z}rkS%`ƻCk6@ϒHqRKrZ8EۢﰨMIᱭd4"$ VPQvN.405i=fUw]0t2 )"Y0[yw{9mQJa723wiLb+sh ?Ȉ4[e\4V5I8^3 J= zazi4L6)j p@X8%pek '5|*Vo9ʅ7  ,)d?e#)%Ci oyځqd0pqvvNEv;"MI~*zMԻ;\qˌQ k&aɳ>sd(T8׷=B \,HO٦;~:*)S$EaNN \D=p5>ʋY??ƀ4czDm+ %o) :g纇SMTsvv DmHd/T'LE(d"AUҩwW8rV\PُfI! ?+h?F_G39'$F!b,7{/3~mš5u,GU;ߣ‹sSb9%Oňi"@N)o;`m:QL$v|YJ^LEٿ]s_(8V` Й Y]y<VpS+sh/vg7ݐq, izAVU=n m@| T dF ˰gY<ˢݙs߿/lFEO[P=sqpb )$;PW~~(Q#j9 )1ºH¡,pΟ5ߕ!H N|qA2I沿@& ІGaUs~/Ơx|@.~%ԃ D1 ʹOli<ͥH!ٍ-{m nhEW]& 1RF. 5^ Uv51 M>y6ҹK0Kim-$FYYNHqKim-rQ&G8̆juhd[a"b Z2tiٛyԜpw(#/>|glHu 7w< `<-]I78 @< 䀴@m pZr, ŝxx,j6żS`XL ۂ@s'mm9kx!{4mSaUj#6G~lL[>rfm30k nۙ]Sf9dz4Mi;l#$RkC]>4 ) 3 &C:)MMnTs,Qc`̍/f)y$K0q2[3PF "_XU#gHpXI 7r(,[J6O)bB!GWKH!Bl轨idVR[ { Bj*'qhy"U`PDR "<,94$i% !t&ٶ, ޛڀl70- 0J:@`2Ld4:2`4B@BR&86D~Vm$[^zkVKl&w03k0fE^6FBa@K c]bmBR%jR2@C9 {`L͈XZDPs(I TN̐#]Bܚzd-$pC r$ YـhpbCۀZx$쭩6d=q rݐttX4Y?%l3Bi\4WIg q=nYSmh`0yN/haHH~+\hQX(R[FՒ$I6DosdX][a ͆"w!h Me/՛O!A3 ?]U0333 /uY]Ŋ}ihVP'd̀|YeC͓bmM3.8(&Μ?:2ѯNSΞ:ǿ{7 ̚n;. Ē ! en3&9j6eyq+yg% @ ¢VY[ϣU۠s8&Q$5^"3hv;^erME|'Vlg"JwtFJs mKLPXT$/s-gK3 1ޱ`0 QSq&~2٨P glLG`uD Pl 9a/T̛ T싻֓'vCe83=a:B̘~,sbCD1BY :62):oC d".49,-med2i8͹r6@lPhzsVa9Y͘v% |H" H(T+Wg-FYڶEYSHg$ rf֧RI٭3OgQU AAdRsû>e|Pa!Ex } ٚjA3磣6'WTLYii,4gQٗz\3Z. G [YΜ^{kQj4c*( q K$”ZnӥbbA6yN>VF=+J'Gn^} {нő 9Be>w:6E"vnt332 ȫlj8Uu Ƕ׻PVʕ"a(YV"w74GdcѢ 2P@9#%v~V{L!t*`)S gRD6:x=]wbL&5>T95C/sl2ñluŜ8FFJ(R@9 k,DbTP~[oZ#FR'~}rO09V[p WAĽMDgOք%}tv>#nyjZʼn,} `B.^yw)upI oalzѢsNp[!X)OPRrjjTjd2}U  I?ԛP˿E><[/\ K k[JdqX- "4))2a.^ᰠ&4M(Ijhu)By kE3s='Z2WVw~{4 Q֠eg4Wp;;# rø_޶^O܏=K? N%Ri} dy_p$FmX̗M*ZjvDn7! IJo@qaa14,{ցV+,gWٯR=Gpq}}=bIDV5^!OG%0`SYFƨPȼ@ RNł!tGoNj&ĺz)p3)4IV7+3/~3uw^w axGi˴Cȃ`x~pDi3 X4GD Gl%* s9 $rB @l"2?>ٯUG4LF> ȄOe3 jLʞ`*0rw@oT?=z6샅oo(`3>'H>)l"V0C8֬,ò+&Q%Cjz<5АmԟI_p krʳ#] 9s_y=e)֣OYn 0pZ5hP<'~ aN|v`[$ ЀDfK>ŋ'``a#İQZ֩)`/=fgҶq8PtK4#l / ;]EG|ɔ!g 0g x?hǢq' Y`{QL)ON=)C+'{*TP)>SKΦ8r7xezh-*o.H%Y}'ŗ2"aNEhHyj* !2`2 ثA- 8+KSj:Bp~' g>zT[N4mN!B-,.Ak9c˱S ^33 &fx"̊W݈UlOu \D^|0B1XdnF^ Lsv^DTp0ڌ/]dS.12\+)#" Q1'cQEFhȕ+vq_,M^{qV"/W!Gc}>=QZktٜed{VwtDl6nav~xO߅&a=o A̟)uŊ̀~"/9Az#Eh\:4m;K RD3oU|Ӧfϥ*P+g*=[oysbȦwmun, }5[n \#-,-<ʁaP0 ۽jeיrՌkϧ#Elvrz0*YgÛGJk,֐VM[ƉA@ A1|^bHUVֲș,x-^xN4H {a-ٝN:ё'zOuP"˪ Ƴ@ # 94n$P<YB=JθýI ޢ>&aie0׵?fU#-Bi OKq,nȖA{swDgn(5ՠ D̾ܨV˼I{j6',Ebê|:"yt9{[|\/Կ[pN>{33lCzŒ:3vf^I1J 7;=pR:\穀)HVivb|wv},W32oEܽEFُz\zqrr2ڔv~t!3opo+iQ?' @0{9a_O G!ҥ0Er>iUp2 .R-l給FnK3}aD8 /76bFpzb@s)JK4>1FFR̤b Q&`*r\**tE5Us\E9}☛C쌟S7kwJ LߙI$k7>6Y1B 7Wc>< b7nʠDv{˖TF4{i;R,VgsՐm 3c&KZ]Ę-}xDQG`'ǥx:dr#Ri0_ L"\pNŇG}BR,X V Pf:Se#\WF8t!hZ!U/]FaPgPI"JD r6ѶE\fcrg#V Cb'&[Mm Nс#x =A/5|g6JD,"ӭ-6Ӵ]< iCњSH|.& *i> dәy55" Q]@k.xJe^'(Ss*WOVG{m"̯6LDS#2r&Ԁ:lwcR jUca"ρa-bB(kI1xyShꪻ@#3) iZOɛ^[9%{Px ,!R?slC'6Բž{T@D isM%T֪܏=csk vctlpҷ h0(C'9$Mr,1dˍ9'vSbLŌa ՙY  R\BAeK\§CT[xV~o`x]% FsMZ`e`h8??y>J{so(G>J m⓰ÁMr@XaԇkO/TKjJVƶ&ѠfԺ7n;_}+'x*FjɕKxYK=crL|;SyZ$=tC0ctLP/;_/{r窨ƝޔN׻:c7*2^;Ǩcz)W QB%V-^Ar6X'ZDJݹnoS >95@ G)wVx:פo V>V?{O0R)$ a5\,`qYVpTvoB= f_R# *SAϼ=\8/kIt]bi; K`b킼`*mgFX.t*K-VKcРq F>ZQӢ:̺""Fìo v4AEʳ]n߀mʵڙ ϴi`4GN(i ۔?R#{ bH3;B ?b/y4$8 ق1O]~P7q!Ghl#m4ڞzCA>{28^faۼ|T|SM* ur(I?XM囄904pkȯ˯!1 6PP0$ 8WP@q p ~/|ހw‚:`ԃ`mJd~gK>(*d!w<=y\zL~S+?5;G9GxWS?q)Ĩ3RsfR(krҦ'WҪąz CLT?1|7"[& ut*m9}xǃ͟};m7Ѷ|gQǃatfۥ !K;6?/t>9]JvQzNB/ $ /LλbXY. ~e@\$& Zs٠īOwy{N~8!?J̰0!]f'dD pt ))wxh[!6"4ϙUPaӠ+>S>;u)ZC4>K ef'ʞ QeEcB8`biĦvGMhH:뙛TdxV8oB,^ǖUsrwH]`*LVߕ7f9ɯ"}L:_* C!]&*e.0WWN> a8 RV߾9!#'LނlGsٲ+b#JX+^U^ɯ@җV$d-+Kv}L0غMX]ԁZ[g9qHح`JPKkmRft ` >~盒 wkbay btM՛StJ St"@yBJI19-c<ng=iS1[Kl%l u25C *QseL Rh4L'6uw>_Ï613PL4 @8H X,0z#.~@!E$887.`QuBDPV1hL7% ' IU#0@0 (`f+? ^DPɷNW!ac;-*֯=n om[/ϔ"[Rw~{F;zw7Ӑn3p/0c}swiW#ɒZ} >s4nĢe8mtdpAHb͜"˂:C&cNUx&N?_!ea9@>N:U }WxNM,r Bd(af3l0w^~=fߗ b)VSuؖJD#fQ r]#wŭ; |p"ȉz~`FeNK01uKvzjd{|E~#_{m[h@ #!HVG9X VmL\V]l6~@t:;l))?z~:HY;IsN@6l.\((k`h0 XIQ^y\!-Ÿޛ ÐHR5z{~ K5*>:yP_%i6 AIE]=#uSE6 X-iKջz>;E>eN 3oۜN|h::MDw?=|~?<dL岓gZn#*ֆ0>T<6K gчB1?Y T@L̕ |\BO!.,AAr(E,^qOs\sE(ٗ'!1Lb<Cy2L{7ӵ1)N3kݡڗp4Nv`>|DI d٭Y[~C*A%F :~4T{=x|2k]X$o [9:RGRZ' > xV5W|l~{vkvH ^RJDm'ڜsN6]E"%DrA0XqG#-!G>q0o#cB cf\OyW~Bq{ OYcL(k2@{#I :AD| zբ})d VLT~xNI]Xxu'v~>al_Ŕ!~Lp *l88b@Y{^Lp$$Uy_DB E~naN|93qCI P'o_Pcu]`G tsL*9>=0%p<ٝ?4]AWMT!揮Wt}z{z e Yn7נ)KPUUWUeSӢ @/G~;6Owޖ=- Jۈ\[O[x~lP?̛΋=ߏQ3BcU3?@&V ` 1%_8>?gw6EQlr MaHy!B6tftL B^Q y_0OOx4' DglBDP7,gU9<qx7۾\F**q%(ѺC澎OgK0a L0  02PTX y*2 2*D? ")9PFT_0P|]#"nIO}>@H U4Jd,x2: &1ݞ`QCe#s&3?neO F{Nyq/fXaڑbxxd  7QLE1?Ur|Y1?~kBD$HmF1@UHɄ9<Q! g8OS ѴT\GbGY~ :yްt$F϶L {ծ.sÚvLDP"dLF'Mf(r~݋p|ϠUoېmpC#pEqn`?\n s,;m,`B,KXnC fNlcP-J;,a.欧N== sz}3IBB X ̧d c6\„O{c`|9Tօ0FElAAaHn~ǹ:Rɻ?Y>Sy)9|,ܱ͒FXq`L>OI-N7 }t= e!0 F{01™ >w*{ A'Gh 9eEL0@M08i>苽o e L;f#<r媁}Sl: Yke(O ftkWTZWd<% wEvCMtн&"trR8т89r^; f!QfV"3l!D. tSq(~#llvI 6H#톐}g&dMN×2ɟVc?8wcΚc>$r/D(G;u8B [fBj%콛5$?Yk.3 m6"iPL K[1~#ɪ{@bХ] pQKN"<*B%Zvv`Rö_fζ>8w0(Xj`Ba$4k"YОؓ2L`JL, 0Ꜷ^59^Ƕ9fa06 f%FL{<U7&lw17s22o—y~OeH;S #|^t\ q7 ]y Bl,B\QQo^~y&`RBk <ʱ|38e)#^*<}(gd 2Br[a?[{1"R: xt`=CotOt,ؙBxoT>> &ȜSy&AlLy#(By$$ mdG 27vS7-3X-} 0ֻWA}1Ш.L_K50#dq3l@eZ]] HC g>(YVazxDw?fÕi;\ NGHqvR4 k$!PPh$ x @ od@1B!M.xx9`bMe"(]28kCr`kxfl/ᶎ]b"_U044md$3nCbjlsroT. BMHd%߫!#}pBMn іZR1-dgyzk ޽;x f,&4&eBveD!" yN'};ZW+f/e1LC/ED)L#g|>2r۹ZrȓEeFXmF%d)0(8fG+hi[1s"FH W qGF}{zz2;Ar2Ϡ;gzC 33LqŊhdrX*(bLB#xWrʼnjӎf@8.`9+Ěi:֡5P&텦9ϊoiMhK ws$I&F.܋pcɡhR% f\v¨0dҡ&%a;ÿ[mN<bkB@&$AY!/9jKߥP4y~:vFʁ*X6ms&8;3" ~s@a{@#cQmD S14^ { n\;ǽ T╳$[TF "@@@+t3.$ND>C;!uəqVwpQ;D&t'}~rfG6 `4c`.=rx!å pfEI6:?=su=og6`Z͉tT}HS`~Q wnov9j~Ϸn0$PuRD/g٣xM 2m)@#"q6yT m$I@Bt87B@X#;} . <"գV(n(f za\L* ڙ8JgY׸#a {J˟d$V!T,pY?I3eg3z0D@zR@P1 H|Eb)>֬5  ^D9BB0ہ.ð|y`oleCtA( }ǖ[2A 젇,^Tۯ3TE($@|OߛO} #{>ۦL3hk5̠ eM3-|uXIVJ"1p=kAѯ? @HȀ=z6.WN@{@4p ^Z fA* eaN[]B@?NB׀7|%yP-XA8r"#)~ȦHI.fT% @#av_ѹSjvi﵏c7ĝ|aܥb/~-EIَguj4tfy2sGB;h0X&<&O]=QzRެ%GgJ$)@h@km(!=jHOf!|jٶz/EU< L/ɐP$sA=y!I-j%)wnTyV0I$chOlH#76l4\ ,$U&0Mw Pr[=BDY^'rȿaCF%G\5@VHFb+p 8!ZYA]:hN ls`eus0Zj pA H+<*wHyLX @:ǯtklPU0x p Gх0Sv8t(r!t7öMTAᶲy}8x爨H2!" @H " H2&oBGg 9 PBBUtK!nFxO1bJĊ"BA䔦H^xѦ>lqO3z}guH{D;@QY$ Jfтr: lѣLAy P3wP v;dc"%w O U۔A0! FFEXđg!vr O_?ԋswܺ(LLƵN  *}VaGA> @?Xe{3/=z{J??O8T+ֳ'h9w1&/JsPuHAh*%h>H9ЯCn,㽦{|hǜJ& `ɉp%W2+|{j_Z{bo$9JgHuVcŏ~\* +39Q-hz~F_X.@s'{ < d|2pJ(#''{KbWzvc"7*@]N i!;1?Whkp>6R˪o褮ЋCʲ, k/I_PUI Pb"n9KrfcG2xU4ڹ=/Xza(G ~u3wH>g;]URI>xնbp^ ]Sip72&'s@;^DN.ܮNA@D#$favsw]{S5'.VerDJh>+٪`&a !MrI&!Ŭ $3,DTy!ɰ% Ȧk r󚔮dMUIEBҎK8,m|0Y@98 f:4ЩcMt Ra p^H;E{6">lP4':P;Zq׵z_|m_GdFة&_<\qrp: h;RxBdx)[aN MΠnb&Hi)~ &;Z f`pYL6F5FM6J&[.ު@@# w@`eһfjVx| ͗(&gF?F'9iV#h^QxAc}z^@PڀqA|/+қ@fГ32n(v!Aa]n! :C+H3S3c[D U]A/&R(rZtZ.dsDz$oM-g ēED[)_e <)g0 f_^&H"n{[},ZH% C@RAxT~T>u ,<^rqD,N0% {;M\UlT|כ:2߶$u_`i}"M+%>3-[ D,ap_O_PՠE7LeX%CϑY3툁g?KIhk=94&D$5ɘ\̆`·S46jH'{]7kT.* A`gh*f I4f9@Hk, Gul9@jam^4B-L 9S\5|~{^j\|ĜѸ}弳$=Ny")jHM0.\ "(^dBi鮿a>{P$@ϟXM7qc׀saB :@$$` FED@$A$;B%vJ>zRlԾI!;::3X!Yƨ"NIh8/l_d&PskWk/ ;"ZT G:ID$BƁ2#߂iDkYA2DR1?r~Jk#2Q,m!@Ӆ#1rmm65h]!.XB?" 6z)8qkP**0uHMv6B֨o8c-b͐(K0wtN!{D:uIoʄp\K5 ySxB!g} `kO(8 ^, Y0H-}8`ʰ׍8{ ]sna>n|.NTyX3WS $!,K8ARr OuxE}lQ{ H ֧]=o*߽dC;*?*jk!$v_e'nT>^tv 춓$m@{, 6H fش~* *#`,X&m;A"!en" T+ @>ʟK6%DDIbna2 11A3E[^`G݈{@s&d7D`}> [\s2U>YFݨn)^^=Y+NJCְ[Tyķ&퍆/v3N# ̛Aqg f;c70y=?1&~n:أhQ^5'}x~l,k[t# % VjqG3.dt HU`xW2_=|>N^(\]weGst ?#-ca7 FA{wWg&8@]fls. oHi8op(<\bۓB& ~>`ú >10 aNġL'| c> Gˈ^!@ 0Oa٥; Y2?QV'aCC6)eYzJ\7=@x.*rlahx   5"@"& ^ +ɎVk3MHs NRw͊ h%5 Ae A],y`0"d G{揟K Zی7xt@C;&#m=4{c<)ɽc^)`v:-R8ʶ:A` 0RIe&hKLaw] s@Jht5 `@>"{t>(}@3 _zBaTr@&ͿmH珎œƙ<NΨ'u؎\ ީ˦tR]=H.؜IV<_2!no=*1!D`#|9!FBހ`1$&ߗ҂f4Z]؀R^*5E9c~ş}喯2<dˊ2*+)mhpz> ^4 ]G@o@gO&g"@r/./ /? v:ofE~<~̄ E xT2IOZA&5 > b1 -^}C_Uץ!|_m k|5IS۠gS͍&[&J ϧF5043f`LۓU7oE5 =|yHc_w73HR1JXP 5: 5H|󾣫gӥ N ܄D2lȬ]@CY0Q |2rnC4j1L \#a D9+8}uCz&*i"X#+ RT`W%,*2-&~?_O4ݝa*!o\pHECBh1)-Zp|19+c$sG`S^'DDoL!^=StDL @˭M<5}z>_' ^EhypYB4% $Z߫y/Wbu0(C-c7)]ՒC^.Pt_o\gf1-:gO#I48.V_ ~'t5e8j$dD{*Oia'pWa5VTr>-vw E7nFhH#j~:ѽ "~^5i*jP50i T"8*sJ55rn+Y)Qo`@0PsF`0J뤮8k |m 2 !ޣ|/'`D_|!O $D"EF2D,"UAA2<9r @JH2?E3$NAJ09?SL\yÒt]:~[dW~BZ1! F9{ݛ&?AAwT061Hs QM@BFGVMy4{cX s@uW46^>zUOM5aݭԧb `! f>@q\\CK&>|,UTx :|-ruʧGQs'{CiA"j-^`ةɲlM$9!?frL%dl@Gk jTm}Kzc7OʀuLӖeD B٢^1Odo6/Km}}_wNsݩW!aex었X`U+-=qyVִٿK0UE@B@cNE`Xʠ}8%-4'27]n-"_$T_H6|y<q;hu?b&,8A)l/zl۝dUk K?L _{䇟x}ӷ^!qt.Ctfo.5d61a%^ֹgOˠ|9#~7̳S?^ k0rv}3ksKB@L*tWJ9Ù1*fЍϚ4rFi]F8Trh,1 qqWnl~V;Λc˫wn!XL~\fFurwOePu:s $f"gUfV;u * 8.Ll]>3hc_xcC臒 0xn-f\maBPzKt=PZ^*M2lS"w]NU=TWHɪrAO7M7{WPYe|`%o Svoggҡ.(@ $P* 1#@~YL6=od|X$"[erceĥ6mLI*<̇0|f 6;m_4EIN3H3>SkLүI)F=^ ӂhE@s5oQF*Yw2q4WbFz2l[ uf\0E^&p]{@ӢH3*MXg-Հ &a"Cُߒc%YOP6}Nv2I蟻" [$E~(s('{{AMM6NVX\"AqӲ39Zw (N3G+4$$X(*jHuX% `ӄp< CΪ-zp{0J HUp9>&D/?>oR絲MuDNXXPBFtN_ɍqAf8]H Y$ bM( 9g(LV%RxD/E 9$-@!^B,3_p|>TĺA"˳Ø6< D1` G4b&H!;/c 3>j1X(@kQ{7b& "hBr Z_Qk(E-..`hqsgѕ E;P"<nr܀&Rv\D{Vsxb*`Cs@1m`\&ɾQMC6taa7a)9AhrĬ{G:sW.4ȱo0 AAF9 #n@Φ9<$C(Wə =@iߋ^+JCevV:L;G,W2U!&>pbpNkܐ( R,mHYBtM` H$2!]yb' BRW} w=qܴM`EX@T'ЅF@ 1AM6#8gQ)y9_@Zy3@}3fyJI$MVW+^2Kfrm8,YI(6˧q %@h H+ /DjXhP n)Ou"v7!~aКCGz8B1&&mF YH 4e@P?d4,xW1vc7/XezkWye|\>: z 0APAOSl  Hp#$"@C- @5.hK[x^}xpgY7@44*2YT=2;N+q c鵺uQM˖Lw|>n@:WT9r@7@`>/n8By>&gBtBw@5RfIG♡n㏫r}WA $; XٿOgKJ_e9xYXy~b١Mq7j\mzoA^vp AavRP#x=ukix2дF>x0:}vȴ[_!J{}wڏ.=ߗn, 9LBo|?1x|W ő 9O}#!L@xwX C^z_x9)l0NT.> {]+0nKeF֋@VwA`p:3f;RFwcgeYܦ VEY Z˞FBQP7";%wLzNp@QWz}!&o~ HT y?<}ӿ*u'gջ. Ђ=@"NK\%L^=?e|̅R)zxځʟWymJ>s]xB)܁N`j;ȆX )z N倫;9LT=TzRaJ v;N(G ։h4:;0Ґ_8Y8?=seP1(DR N hI|&}t5էɃL GYOggaD*@F@9^iP8J@"&R{[^$u1Zu'$%Foϋ}{*.tnP(!##̙0H  ȩ.vt::z5&_V?M8wY HXMZ,S>_每 nn`$}RdF"WYjv4`|GQ$<'Ar*{cd2 Qd|Qc*gD->OlK8 rf8of#ȉ&pBh(B@ۧ?D=,QVP,I뽆7/)lD"2~1 =T `)NBgMFFBB譄@_ ;hП|dIt{{~.t{Eե~|qRsG5PcpohjM菽r3Cuk9Yiy,F8>B[J `em# a> ݀8\E/9'[Gf[9H]-hR%i$[2Zb#X ӽ7~1 0S0`UBneXܘbWP3ABiulygwvz;m8p{ZB!|>hB[B .S;z,꛶lcd^w90$F#a/mN~{<rӆie1x.#'ƒ֢yu> B]-VdQiYH G*\xWc?_8RTr 1 vD)q1_cU~\R9W$$wa$.{g6א(⧺orꂔ c(y/ڊ/&7GM\ e  :0c eml> R. aS5Pp(fV lk6ƃ&9ghByg?g#[`:Э.넡\5`(/I=Oe9{?WcǍDYKbp<]vvjE&})ebqЕ a,z iqP"25335+XgysVeEܼ=|M(af؈CͽrE8P~7xml2/tests/testthat/test-xml_attrs.R0000644000176200001440000001647013637417153017275 0ustar liggesuserscontext("xml_attrs") test_that("missing attributes returned as NA by default", { x <- read_xml("") expect_equal(xml_attr(x, "id"), NA_character_) }) test_that("missing attributes returned as NA", { x <- read_xml("") expect_equal(xml_attr(x, "id", default = 1), "1") }) test_that("attributes are correctly found", { x <- read_xml("") expect_true(xml_has_attr(x, "id")) expect_false(xml_has_attr(x, "id2")) }) test_that("returning an attribute node prints properly", { x <- read_xml("") t1 <- xml_find_first(x, "//@c") expect_equal(format(t1), "") }) # Namespaces ------------------------------------------------------------------- # Default namespace doesn't apply to attributes test_that("qualified names returned when ns given", { x <- read_xml("ns-multiple.xml") ns <- xml_ns(x) bars <- xml_children(xml_children(x)) attr <- xml_attrs(bars, ns) expect_equal(names(attr[[1]]), "f:id") expect_equal(names(attr[[2]]), "g:id") }) x <- read_xml(' ') doc <- xml_children(x)[[1]] docs <- xml_find_all(x, "//doc") ns <- xml_ns(x) test_that("qualified attributes get own values", { expect_equal(xml_attrs(doc, ns), c("b:id" = "b", "f:id" = "f", "id" = "")) }) test_that("unqualified name gets unnamespace attribute", { expect_equal(xml_attr(doc, "id", ns), "") }) test_that("namespace names gets namespaced attribute", { expect_equal(xml_attr(doc, "b:id", ns), "b") expect_equal(xml_attr(doc, "f:id", ns), "f") }) test_that("xml_attr<- modifies properties", { xml_attr(doc, "id", ns) <- "test" expect_equal(xml_attr(doc, "id", ns), "test") xml_attr(doc, "b:id", ns) <- "b_test" expect_equal(xml_attr(doc, "b:id", ns), "b_test") xml_attr(doc, "f:id", ns) <- "f_test" expect_equal(xml_attr(doc, "f:id", ns), "f_test") xml_attr(docs, "f:id", ns) <- "f_test2" expect_equal(xml_attr(docs, "f:id", ns), c("f_test2", "f_test2")) xml_attr(docs, "f:id", ns) <- NULL expect_equal(xml_attr(docs, "f:id", ns), c(NA_character_, NA_character_)) }) test_that("xml_attr<- recycles values", { x <- read_xml("") a <- xml_find_all(x, "a") xml_attr(a, "b") <- c("e", "f") expect_equal(xml_attr(a, "b"), c("e", "f")) }) test_that("xml_attrs<- modifies all attributes", { expect_error(xml_attrs(doc) <- 1, "`value` must be a named character vector or `NULL`") expect_error(xml_attrs(doc) <- "test", "`value` must be a named character vector or `NULL`") xml_attrs(doc, ns) <- c("b:id" = "b", "f:id" = "f", "id" = "test") expect_equal(xml_attrs(doc, ns), c("b:id" = "b", "id" = "test", "f:id" = "f")) xml_attrs(doc, ns) <- c("b:id" = "b", "f:id" = "f") expect_equal(xml_attrs(doc, ns), c("b:id" = "b", "f:id" = "f")) xml_attrs(doc, ns) <- c("b:id" = "b", "id" = "test") expect_equal(xml_attrs(doc, ns), c("b:id" = "b", "id" = "test")) expect_error(xml_attrs(docs) <- "test", "`value` must be a list of named character vectors") xml_attrs(docs, ns) <- c("b:id" = "b", "id" = "test") expect_equal(xml_attrs(docs, ns), list( c("b:id" = "b", "id" = "test"), c("b:id" = "b", "id" = "test"))) xml_attrs(docs, ns) <- NULL expect_equivalent(xml_attrs(docs, ns), list(character(0), character(0))) }) test_that("xml_attr<- accepts non-character values", { x <- read_xml('') svg <- xml_root(x) xml_attr(svg, "width") <- 8L expect_that(xml_attr(svg, "width"), equals("8")) xml_attr(svg, "height") <- 12.5 expect_that(xml_attr(svg, "height"), equals("12.5")) expect_that(xml_attrs(svg), equals(c(width = "8", height = "12.5"))) xml_attrs(svg) <- c(width = 14L, height = 23.45) expect_that(xml_attrs(svg), equals(c(width = "14", height = "23.45"))) }) test_that("xml_attr<- can set empty strings, and removes attributes with NULL", { x <- read_xml("") xml_attr(x, "test") <- "" expect_equal(xml_attr(x, "test"), "") xml_attr(x, "test") <- NULL expect_equal(xml_attr(x, "test"), NA_character_) }) test_that("xml_attr<- removes namespaces if desired", { xml_attr(x, "xmlns:b") <- NULL expect_equal(xml_attrs(x), c("xmlns:f" = "http://foo.com")) }) test_that("xml_attr<- removes namespaces if desired", { x <- read_xml("") # cannot find //b with a default namespace expect_equal(length(xml_find_all(x, "//b")), 0) # unless we specify it explicitly expect_equal(length(xml_find_all(x, "//b")), 0) expect_equal(length(xml_find_all(x, "//d1:b", xml_ns(x))), 1) # but can find it once we remove the namespace xml_attr(x, "xmlns") <- NULL expect_equal(length(xml_find_all(x, "//b")), 1) # and add the old namespace back xml_attr(x, "xmlns") <- "tag:foo" expect_equal(xml_attr(x, "xmlns"), "tag:foo") expect_equal(length(xml_find_all(x, "//b")), 0) expect_equal(length(xml_find_all(x, "//d1:b", xml_ns(x))), 1) expect_equal(xml_attr(x, "xmlns"), "tag:foo") }) test_that("xml_attr<- removes prefixed namespaces if desired", { x <- read_xml("") # cannot find //b with a prefixed namespace expect_equal(length(xml_find_all(x, "//b")), 0) # unless we specify it explicitly expect_equal(length(xml_find_all(x, "//b")), 0) expect_equal(length(xml_find_all(x, "//pre:b", xml_ns(x))), 1) # but can find it once we remove the namespace xml_attr(x, "xmlns:pre") <- NULL expect_equal(length(xml_find_all(x, "//b")), 1) # and add the old namespace back xml_attr(x, "xmlns:pre") <- "tag:foo" xml_set_namespace(xml_children(x)[[1]], "pre") expect_equal(xml_attr(x, "xmlns:pre"), "tag:foo") expect_equal(length(xml_find_all(x, "//b")), 0) expect_equal(length(xml_find_all(x, "//pre:b", xml_ns(x))), 1) expect_equal(xml_attr(x, "xmlns:pre"), "tag:foo") }) test_that("xml_set_attr works identically to xml_attr<-", { content <- "" x <- read_xml(content) y <- read_xml(content) xml_attr(x, "a") <- "test" xml_set_attr(y, "a", "test") expect_equal(as.character(x), as.character(y)) bx <- xml_find_all(x, "//b") by <- xml_find_all(y, "//b") xml_attr(bx, "b") <- "test2" xml_set_attr(by, "b", "test2") expect_equal(as.character(x), as.character(y)) # No errors for xml_missing mss <- xml_find_first(bx, "./c") expect_error(xml_attr(mss[[2]], "b") <- "blah", NA) expect_error(xml_set_attr(mss[[2]], "b", "blah"), NA) }) test_that("xml_set_attrs works identically to xml_attrs<-", { content <- "" x <- read_xml(content) y <- read_xml(content) xml_attrs(x) <- c(a = "test") xml_set_attrs(y, c(a = "test")) expect_equal(as.character(x), as.character(y)) bx <- xml_find_all(x, "//b") by <- xml_find_all(y, "//b") xml_attrs(bx) <- c(b = "test2") xml_set_attrs(by, c(b = "test2")) expect_equal(as.character(x), as.character(y)) # No errors for xml_missing mss <- xml_find_first(bx, "./c") expect_error(xml_attrs(mss[[2]]) <- c("b" = "blah"), NA) expect_error(xml_set_attrs(mss[[2]], c("b" = "blah")), NA) }) test_that("xml_set_attr can set the same namespace multiple times", { doc <- xml_new_root("foo") xml_set_attr(doc, "xmlns:bar", "http://a/namespace") xml_set_attr(doc, "xmlns:bar", "http://b/namespace") expect_equal(xml_attr(doc, "xmlns:bar"), "http://b/namespace") }) xml2/tests/testthat/test-xml_structure.R0000644000176200001440000000126413631515545020171 0ustar liggesuserscontext("xml_structure") test_that("xml_structure", { expect_output(xml_structure(read_xml("")), " ") expect_output(xml_structure(read_xml(""), indent = 0L), " ") }) test_that("xml_structure can write to a file (#244)", { tmp = tempfile() xml_structure(read_xml(""), file = tmp) expect_equal(readLines(tmp), c("", " ", " ", " ", " ")) # repeated calls erase existing content xml_structure(read_xml(""), file = tmp) expect_equal(readLines(tmp), c("", " ", " ", " ", " ")) }) xml2/tests/testthat/test-modify-xml.R0000644000176200001440000001634213637645657017357 0ustar liggesuserscontext("modify nodes") test_that("modifying nodes works", { x <- read_xml("") node <- xml_find_first(x, "//x") expect_equal(xml_name(node), "x") .Call(node_set_name, node$node, "y") expect_equal(xml_name(node), "y") expect_equal(xml_text(node), "") .Call(node_set_content, node$node, "test") expect_equal(xml_text(node), "test") }) test_that("xml_text<- only modifies text content", { x <- read_xml("Text1text2") expect_equal(xml_text(x), "Text1text2") # will only change the first text by default xml_text(x) <- "new_text1" expect_equal(xml_text(x), "new_text1text2") # You can change the second by explicitly selecting it text_node <- xml_find_first(x, "//text()[2]") xml_text(text_node) <- "new_text2" expect_equal(xml_text(x), "new_text1new_text2") }) test_that("xml_text<- creates new text nodes if needed", { x <- read_xml("") xml_text(x) <- "test" expect_equal(xml_text(x), "test") }) test_that("xml_remove removes nodes", { x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] xml_remove(children, free = TRUE) expect_equal(xml_text(x), "") }) test_that("xml_replace replaces nodes", { x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] expect_equal(xml_text(x), "123") xml_replace(t1, t3) expect_equal(xml_text(x), "323") first_child <- xml_children(x)[[1]] xml_replace(first_child, t1, .copy = FALSE) expect_equal(xml_text(x), "123") xml_remove(first_child, free = TRUE) first_child <- xml_children(x)[[1]] xml_replace(first_child, t3, .copy = FALSE) expect_equal(xml_text(x), "32") xml_remove(first_child, free = TRUE) }) test_that("xml_replace works with nodesets", { x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] xml_replace(children, t1) expect_equal(xml_text(x), "11") }) test_that("xml_sibling adds a sibling node", { x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_add_sibling(t1, t3) expect_length(xml_siblings(t1), 2) expect_equal(xml_text(x), "1323") xml_add_sibling(t1, t3, .where = "before") expect_length(xml_siblings(t1), 3) expect_equal(xml_text(x), "31323") children <- xml_children(x) xml_add_sibling(children, t1) expect_equal(xml_text(x), "311131231") }) test_that("xml_add_child adds a child node", { x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] expect_length(xml_children(t1), 0) xml_add_child(t1, t3, .copy = TRUE) expect_length(xml_children(t1), 1) expect_equal(xml_text(x), "1323") children <- xml_children(x) xml_add_child(children, t1) expect_equal(xml_text(x), "1313231313") }) test_that("xml_add_child can create a new default namespace", { x <- xml_root(xml_add_child(xml_new_document(), "foo", xmlns = "bar")) expect_equal(unclass(xml_ns(x)), c(d1 = "bar")) }) test_that("xml_add_child can create a new prefixed namespace", { x <- xml_root(xml_add_child(xml_new_document(), "foo", "xmlns:bar" = "baz")) expect_equal(unclass(xml_ns(x)), c(bar = "baz")) }) test_that("xml_add_child can create a new attribute", { x <- xml_add_child(xml_new_document(), "foo", "bar" = "baz") expect_equal(xml_attr(x, "bar"), "baz") }) test_that("xml_add_child can create new text", { x <- xml_add_child(xml_new_document(), "foo", "bar") expect_equal(xml_text(x), "bar") }) test_that("xml_add_child can create a new node with the specified prefix", { x <- xml_root(xml_add_child(xml_new_document(), "foo", "xmlns:bar" = "baz")) t1 <- xml_add_child(x, "bar:qux") expect_equal(xml_name(t1), "qux") expect_equal(xml_name(t1, xml_ns(x)), "bar:qux") }) test_that("xml_add_child can create a new node with the specified prefix", { x <- xml_root(xml_add_child(xml_new_document(), "foo", "xmlns:bar" = "baz")) expect_error(xml_add_child(x, "bar2:qux"), "No namespace with prefix `bar2` found") }) # https://github.com/r-lib/xml2/issues/284 test_that("xml_add_child can create a new node with attribute named 'par'", { x <- xml_new_root("foo") t1 <- xml_add_child(x, "a", "par" = "b") expect_true(xml_has_attr(t1, "par")) }) test_that("xml_add_parent works with xml_node input", { x <- read_xml("") y <- xml_find_first(x, ".//y") xml_add_parent(y, "z") expect_equal(xml_name(xml_parent(y)), "z") expect_equal(xml_name(xml_child(x)), "z") }) test_that("xml_add_parent works with xml_nodeset input", { x <- read_xml("") y <- xml_find_all(x, ".//y") xml_add_parent(y, "z") expect_equal(xml_name(xml_parent(y)), c("z", "z")) expect_equal(xml_name(xml_child(x)), "z") }) test_that("xml_add_parent works with xml_missing input", { x <- read_xml("

Some text.

Some other.

No bold text

") y <- xml_find_all(x, ".//p") z <- xml_find_first(y, ".//b") xml_add_parent(z, "em") expect_equal(xml_name(xml_parent(z)), c("em", "em")) expect_equal(xml_name(xml_children(y)), c("em", "em")) }) test_that("xml_new_document adds a default character encoding", { x <- read_xml("\u00E1\u00FC\u00EE") expect_equal(as.character(x), "\n\u00E1\u00FC\u00EE\n") x2 <- xml_new_document() xml_add_child(x2, "root", "\u00E1\u00FC\u00EE") expect_equal(as.character(x2), "\n\u00E1\u00FC\u00EE\n") }) test_that("xml_new_root is equivalent to using xml_new_document xml_add_child", { x1 <- xml_add_child(xml_new_document(), "foo", "bar") x2 <- xml_new_root("foo", "bar") expect_identical(as.character(x1), as.character(x2)) }) test_that("xml_add_child can insert anywhere in the child list", { x <- read_xml("
") xml_add_child(x, "z") expect_equal(c("z"), xml_name(xml_children(x))) xml_add_child(x, "w", .where = 0) expect_equal(c("w", "z"), xml_name(xml_children(x))) xml_add_child(x, "y", .where = 1) expect_equal(c("w", "y", "z"), xml_name(xml_children(x))) xml_add_child(x, "x", .where = 1) expect_equal(c("w", "x", "y", "z"), xml_name(xml_children(x))) }) test_that("xml_add_child can insert anywhere in a nodeset", { x <- read_xml("

Some text.

Some other.

No bold text

") y <- xml_find_all(x, ".//p") z <- xml_find_first(y, ".//b") xml_add_child(z, "bar") xml_add_child(z, "foo", .where = 0) expect_equal(c("foo", "bar", "foo", "bar"), xml_name(xml_children(z))) }) test_that("Can write root nodes with namespaces", { x <- xml_new_root("foo:bar", "xmlns:foo"="http://foo/bar") expect_equal(unclass(xml_ns(x)), c(foo = "http://foo/bar")) expect_equal(as.character(xml_find_first(x, "/*")), "") }) xml2/tests/testthat.R0000644000176200001440000000020613631717664014275 0ustar liggesuserslibrary(testthat) library(xml2) is_solaris <- tolower(Sys.info()[["sysname"]]) == "sunos" if (!is_solaris) { test_check("xml2") } xml2/src/0000755000176200001440000000000013643426276011740 5ustar liggesusersxml2/src/xml2_url.cpp0000644000176200001440000001130113640647064014201 0ustar liggesusers#include #include #include "xml2_utils.h" // [[export]] extern "C" SEXP url_absolute_(SEXP x_sxp, SEXP base_sxp) { R_xlen_t n = Rf_xlength(x_sxp); SEXP out = PROTECT(Rf_allocVector(STRSXP, n)); if (Rf_xlength(base_sxp) > 1) { Rf_error("Base URL must be length 1"); } const xmlChar* base_uri = (xmlChar*) Rf_translateCharUTF8(STRING_ELT(base_sxp, 0)); for (int i = 0; i < n; ++i) { const xmlChar* uri = (xmlChar*) Rf_translateCharUTF8(STRING_ELT(x_sxp, i)); SET_STRING_ELT(out, i, Xml2String(xmlBuildURI(uri, base_uri)).asRString()); } UNPROTECT(1); return out; } // [[export]] extern "C" SEXP url_relative_(SEXP x_sxp, SEXP base_sxp) { R_xlen_t n = Rf_xlength(x_sxp); SEXP out = PROTECT(Rf_allocVector(STRSXP, n)); if (Rf_xlength(base_sxp) > 1) { Rf_error("Base URL must be length 1"); } const xmlChar* base_uri = (xmlChar*) Rf_translateCharUTF8(STRING_ELT(base_sxp, 0)); for (int i = 0; i < n; ++i) { const xmlChar* uri = (xmlChar*) Rf_translateCharUTF8(STRING_ELT(x_sxp, i)); SET_STRING_ELT(out, i, Xml2String(xmlBuildRelativeURI(uri, base_uri)).asRString()); } UNPROTECT(1); return out; } // [[export]] extern "C" SEXP url_parse_(SEXP x_sxp) { R_xlen_t n = Rf_xlength(x_sxp); SEXP scheme = PROTECT(Rf_allocVector(STRSXP, n)); SEXP server = PROTECT(Rf_allocVector(STRSXP, n)); SEXP user = PROTECT(Rf_allocVector(STRSXP, n)); SEXP path = PROTECT(Rf_allocVector(STRSXP, n)); SEXP query = PROTECT(Rf_allocVector(STRSXP, n)); SEXP fragment = PROTECT(Rf_allocVector(STRSXP, n)); SEXP port = PROTECT(Rf_allocVector(INTSXP, n)); for (int i = 0; i < n; ++i) { const char* raw = Rf_translateCharUTF8(STRING_ELT(x_sxp, i)); xmlURI* uri = xmlParseURI(raw); if (uri == NULL) { continue; } SET_STRING_ELT(scheme, i, Rf_mkChar(uri->scheme == NULL ? "" : uri->scheme)); SET_STRING_ELT(server, i, Rf_mkChar(uri->server == NULL ? "" : uri->server)); INTEGER(port)[i] = uri->port == 0 ? NA_INTEGER : uri->port; SET_STRING_ELT(user, i, Rf_mkChar(uri->user == NULL ? "" : uri->user)); SET_STRING_ELT(path, i, Rf_mkChar(uri->path == NULL ? "" : uri->path)); SET_STRING_ELT(fragment, i, Rf_mkChar(uri->fragment == NULL ? "" : uri->fragment)); /* * * * Thu Apr 26 10:36:26 CEST 2007 Daniel Veillard * svn path=/trunk/; revision=3607 * https://github.com/GNOME/libxml2/commit/a1413b84f7163d57c6251d5f4251186368efd859 */ #if defined(LIBXML_VERSION) && (LIBXML_VERSION >= 20629) SET_STRING_ELT(query, i, Rf_mkChar(uri->query_raw == NULL ? "" : uri->query_raw)); #else SET_STRING_ELT(query, i, Rf_mkChar(uri->query == NULL ? "" : uri->query)); #endif xmlFreeURI(uri); } SEXP out = PROTECT(Rf_allocVector(VECSXP, 7)); SET_VECTOR_ELT(out, 0, scheme); SET_VECTOR_ELT(out, 1, server); SET_VECTOR_ELT(out, 2, port); SET_VECTOR_ELT(out, 3, user); SET_VECTOR_ELT(out, 4, path); SET_VECTOR_ELT(out, 5, query); SET_VECTOR_ELT(out, 6, fragment); SEXP names = PROTECT(Rf_allocVector(STRSXP, 7)); SET_STRING_ELT(names, 0, Rf_mkChar("scheme")); SET_STRING_ELT(names, 1, Rf_mkChar("server")); SET_STRING_ELT(names, 2, Rf_mkChar("port")); SET_STRING_ELT(names, 3, Rf_mkChar("user")); SET_STRING_ELT(names, 4, Rf_mkChar("path")); SET_STRING_ELT(names, 5, Rf_mkChar("query")); SET_STRING_ELT(names, 6, Rf_mkChar("fragment")); Rf_setAttrib(out, R_ClassSymbol, Rf_mkString("data.frame")); Rf_setAttrib(out, R_NamesSymbol, names); SEXP row_names = PROTECT(Rf_allocVector(INTSXP, 2)); INTEGER(row_names)[0] = NA_INTEGER; INTEGER(row_names)[1] = -n; Rf_setAttrib(out, R_RowNamesSymbol, row_names); UNPROTECT(10); return out; } // [[export]] extern "C" SEXP url_escape_(SEXP x_sxp, SEXP reserved_sxp) { R_xlen_t n = Rf_xlength(x_sxp); SEXP out = PROTECT(Rf_allocVector(STRSXP, n)); if (Rf_xlength(reserved_sxp) != 1) { Rf_error("`reserved` must be character vector of length 1"); } xmlChar* xReserved = (xmlChar*) Rf_translateCharUTF8(STRING_ELT(reserved_sxp, 0)); for (int i = 0; i < n; ++i) { const xmlChar* xx = (xmlChar*) Rf_translateCharUTF8(STRING_ELT(x_sxp, i)); SET_STRING_ELT(out, i, Xml2String(xmlURIEscapeStr(xx, xReserved)).asRString()); } UNPROTECT(1); return out; } // [[export]] extern "C" SEXP url_unescape_(SEXP x_sxp) { R_xlen_t n = Rf_xlength(x_sxp); SEXP out = PROTECT(Rf_allocVector(STRSXP, n)); for (int i = 0; i < n; ++i) { const char* xx = Rf_translateCharUTF8(STRING_ELT(x_sxp, i)); char* unescaped = xmlURIUnescapeString(xx, 0, NULL); SET_STRING_ELT(out, i, (unescaped == NULL) ? NA_STRING : Rf_mkCharCE(unescaped, CE_UTF8)); xmlFree(unescaped); } UNPROTECT(1); return out; } xml2/src/xml2_node.cpp0000644000176200001440000004471713640651342014337 0ustar liggesusers#define R_NO_REMAP #include #undef R_NO_REMAP #include #include #include #include #include #include #include "xml2_types.h" #include "xml2_utils.h" template // for xmlAttr and xmlNode std::string nodeName(T* node, SEXP nsMap) { std::string name = Xml2String(node->name).asStdString(); if (Rf_xlength(nsMap) == 0) { return name; } xmlNs* ns = node->ns; if (ns == NULL) return name; std::string prefix = NsMap(nsMap).findPrefix(Xml2String(ns->href).asStdString()); return prefix + ":" + name; } // [[export]] extern "C" SEXP node_name(SEXP node_sxp, SEXP nsMap) { BEGIN_CPP XPtrNode node(node_sxp); std::string name = nodeName(node.checked_get(), nsMap); return Rf_ScalarString(Rf_mkCharLenCE(name.c_str(), name.size(), CE_UTF8)); END_CPP } // [[export]] extern "C" SEXP node_set_name(SEXP node_sxp, SEXP value) { BEGIN_CPP XPtrNode node(node_sxp); xmlNodeSetName(node, asXmlChar(value)); return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_text(SEXP node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); return Rf_ScalarString(Xml2String(xmlNodeGetContent(node.checked_get())).asRString()); END_CPP } bool hasPrefix(std::string lhs, std::string rhs) { if (lhs.length() > rhs.length()) { return false; } return std::equal( lhs.begin(), lhs.end(), rhs.begin()); } const xmlChar* xmlNsDefinition(xmlNodePtr node, const xmlChar* lookup) { xmlNsPtr next = node->nsDef; while(next != NULL) { // default namespace if (xmlStrEqual(next->prefix, lookup)) { return next->href; } next = next->next; } return NULL; } // [[export]] extern "C" SEXP node_attr( SEXP node_sxp, SEXP name_sxp, SEXP missing_sxp, SEXP nsMap_sxp) { BEGIN_CPP XPtrNode node(node_sxp); std::string name(CHAR(STRING_ELT(name_sxp, 0))); if (Rf_xlength(missing_sxp) != 1) { Rf_error("`missing` should be length 1"); } SEXP missingVal = STRING_ELT(missing_sxp, 0); if (name == "xmlns") { return Rf_ScalarString(Xml2String(xmlNsDefinition(node, NULL)).asRString(missingVal)); } if (hasPrefix("xmlns:", name)) { std::string prefix = name.substr(6); return Rf_ScalarString(Xml2String(xmlNsDefinition(node, asXmlChar(prefix))).asRString(missingVal)); } xmlChar* string; if (Rf_xlength(nsMap_sxp) == 0) { string = xmlGetProp(node.checked_get(), asXmlChar(name)); } else { size_t colon = name.find(":"); if (colon == std::string::npos) { // Has namespace spec, but attribute not qualified, so look for attribute // without namespace string = xmlGetNoNsProp(node.checked_get(), asXmlChar(name)); } else { // Split name into prefix & attr, then look up full url std::string prefix = name.substr(0, colon), attr = name.substr(colon + 1, name.size() - 1); std::string url = NsMap(nsMap_sxp).findUrl(prefix); string = xmlGetNsProp(node.checked_get(), asXmlChar(attr), asXmlChar(url)); } } return Rf_ScalarString(Xml2String(string).asRString(missingVal)); END_CPP } // [[export]] extern "C" SEXP node_attrs(SEXP node_sxp, SEXP nsMap_sxp) { BEGIN_CPP XPtrNode node_(node_sxp); int n = 0; xmlNodePtr node = node_.checked_get(); if (node->type == XML_ELEMENT_NODE) { // attributes for(xmlAttr* cur = node->properties; cur != NULL; cur = cur->next) n++; // namespace definitions for(xmlNsPtr cur = node->nsDef; cur != NULL; cur = cur->next) n++; SEXP names = PROTECT(Rf_allocVector(STRSXP, n)); SEXP values = PROTECT(Rf_allocVector(STRSXP, n)); int i = 0; for(xmlAttr* cur = node->properties; cur != NULL; cur = cur->next, ++i) { std::string name = nodeName(cur, nsMap_sxp); SET_STRING_ELT(names, i, Rf_mkCharLenCE(name.c_str(), name.size(), CE_UTF8)); xmlNs* ns = cur->ns; if (ns == NULL) { if (Rf_xlength(nsMap_sxp) > 0) { SET_STRING_ELT(values, i, Xml2String(xmlGetNoNsProp(node, cur->name)).asRString()); } else { SET_STRING_ELT(values, i, Xml2String(xmlGetProp(node, cur->name)).asRString()); } } else { SET_STRING_ELT(values, i, Xml2String(xmlGetNsProp(node, cur->name, ns->href)).asRString()); } } for(xmlNsPtr cur = node->nsDef; cur != NULL; cur = cur->next, ++i) { if (cur->prefix == NULL) { SET_STRING_ELT(names, i, Rf_mkChar("xmlns")); } else { std::string name = std::string("xmlns:") + Xml2String(cur->prefix).asStdString(); SET_STRING_ELT(names,i, Rf_mkCharLenCE(name.c_str(), name.size(), CE_UTF8)); } SET_STRING_ELT(values, i, Xml2String(cur->href).asRString()); } Rf_setAttrib(values, R_NamesSymbol, names); UNPROTECT(2); return values; } return Rf_allocVector(STRSXP, 0); END_CPP } // Fix the tree by removing the namespace pointers to the given tree void xmlRemoveNamespace(xmlNodePtr tree, xmlNsPtr ns) { // From https://github.com/GNOME/libxml2/blob/v2.9.2/tree.c#L6440 // xmlNodePtr node = tree; /* * Browse the full subtree, deep first */ while(node != NULL) { if (node->ns != NULL && node->ns == ns) { node->ns = NULL; } // Check for namespaces on the attributes if (ns->prefix != NULL && // default namespaces will not exist on attributes node->type == XML_ELEMENT_NODE) { xmlAttrPtr attr = node->properties; while (attr != NULL) { if (attr->ns != NULL && attr->ns == ns) { attr->ns = NULL; } attr = attr->next; } } if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { /* deep first */ node = node->children; } else if ((node != tree) && (node->next != NULL)) { /* then siblings */ node = node->next; } else if (node != tree) { /* go up to parents->next if needed */ while (node != tree) { if (node->parent != NULL) node = node->parent; if ((node != tree) && (node->next != NULL)) { node = node->next; break; } if (node->parent == NULL) { node = NULL; break; } } /* exit condition */ if (node == tree) node = NULL; } else break; } return; } // Fix the tree by adding the namespace pointers to the given tree void xmlAddNamespace(xmlNodePtr tree, xmlNsPtr ns) { // Only needed for default namespaces if (ns->prefix != NULL) { return; } // From https://github.com/GNOME/libxml2/blob/v2.9.2/tree.c#L6440 // xmlNodePtr node = tree; /* * Browse the full subtree, deep first */ while(node != NULL) { if (node->ns == NULL) { node->ns = ns; } if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { /* deep first */ node = node->children; } else if ((node != tree) && (node->next != NULL)) { /* then siblings */ node = node->next; } else if (node != tree) { /* go up to parents->next if needed */ while (node != tree) { if (node->parent != NULL) node = node->parent; if ((node != tree) && (node->next != NULL)) { node = node->next; break; } if (node->parent == NULL) { node = NULL; break; } } /* exit condition */ if (node == tree) node = NULL; } else break; } return; } void removeNs(xmlNodePtr node, const xmlChar* prefix) { if (node == NULL) { return; } if (node->nsDef == NULL) { return; } xmlNsPtr prev = node->nsDef; if (xmlStrEqual(prev->prefix, prefix)) { node->nsDef = prev->next; xmlRemoveNamespace(node, prev); xmlFreeNs(prev); return; } while(prev->next != NULL) { xmlNsPtr cur = prev->next; if (xmlStrEqual(cur->prefix, prefix)) { prev->next = cur->next; xmlRemoveNamespace(node, cur); xmlFreeNs(cur); return; } prev = prev->next; } return; } // [[export]] extern "C" SEXP node_set_attr(SEXP node_sxp, SEXP name_sxp, SEXP value, SEXP nsMap) { BEGIN_CPP XPtrNode node_(node_sxp); std::string name(CHAR(STRING_ELT(name_sxp, 0))); const xmlNodePtr node = node_.checked_get(); if (name == "xmlns") { xmlAddNamespace(node, xmlNewNs(node, asXmlChar(value), NULL)); return R_NilValue; } if (hasPrefix("xmlns:", name)) { std::string prefix = name.substr(6); removeNs(node, asXmlChar(prefix)); xmlAddNamespace(node, xmlNewNs(node, asXmlChar(value), asXmlChar(prefix))); return R_NilValue; } if (Rf_xlength(nsMap) == 0) { xmlSetProp(node, asXmlChar(name), asXmlChar(value)); } else { size_t colon = name.find(":"); if (colon == std::string::npos) { // Has namespace spec, but attribute not qualified, so just use that name xmlSetProp(node, asXmlChar(name), asXmlChar(value)); } else { // Split name into prefix & attr, then look up full url std::string prefix = name.substr(0, colon), attr = name.substr(colon + 1, name.size() - 1); std::string url = NsMap(nsMap).findUrl(prefix); xmlNsPtr ns = xmlSearchNsByHref(node_->doc, node, asXmlChar(url)); xmlSetNsProp(node, ns, asXmlChar(attr), asXmlChar(value)); } } return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_remove_attr(SEXP node_sxp, SEXP name_sxp, SEXP nsMap) { BEGIN_CPP XPtrNode node_(node_sxp); std::string name(CHAR(STRING_ELT(name_sxp, 0))); const xmlNodePtr node = node_.checked_get(); if (name == "xmlns") { removeNs(node, NULL); return R_NilValue; } if (hasPrefix("xmlns:", name)) { std::string prefix = name.substr(6); removeNs(node, asXmlChar(prefix)); return R_NilValue; } if (Rf_xlength(nsMap) == 0) { xmlUnsetProp(node, asXmlChar(name)); } else { size_t colon = name.find(":"); if (colon == std::string::npos) { // Has namespace spec, but attribute not qualified, so just use that name xmlUnsetNsProp(node, NULL, asXmlChar(name)); } else { // Split name into prefix & attr, then look up full url std::string prefix = name.substr(0, colon), attr = name.substr(colon + 1, name.size() - 1); std::string url = NsMap(nsMap).findUrl(prefix); xmlNsPtr ns = xmlSearchNsByHref(node_->doc, node, asXmlChar(url)); xmlUnsetNsProp(node, ns, asXmlChar(attr)); } } return R_NilValue; END_CPP } SEXP asList(std::vector nodes) { SEXP out = PROTECT(Rf_allocVector(VECSXP, nodes.size())); for (size_t i = 0; i < nodes.size(); ++i) { XPtrNode node(nodes[i]); SET_VECTOR_ELT(out, i, SEXP(node)); } UNPROTECT(1); return out; } // [[export]] extern "C" SEXP node_children(SEXP node_sxp, SEXP only_node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); bool only_node = LOGICAL(only_node_sxp)[0]; std::vector out; for(xmlNode* cur = node->xmlChildrenNode; cur != NULL; cur = cur->next) { if (only_node && cur->type != XML_ELEMENT_NODE) { continue; } out.push_back(cur); } return asList(out); END_CPP } // [[export]] extern "C" SEXP node_length(SEXP node_sxp, SEXP only_node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); bool only_node = LOGICAL(only_node_sxp)[0]; int i = 0; for(xmlNode* cur = node->xmlChildrenNode; cur != NULL; cur = cur->next) { if (only_node && cur->type != XML_ELEMENT_NODE) { continue; } ++i; } return Rf_ScalarInteger(i); END_CPP } // [[export]] extern "C" SEXP node_has_children(SEXP node_sxp, SEXP only_node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); bool only_node = LOGICAL(only_node_sxp)[0]; for(xmlNode* cur = node->xmlChildrenNode; cur != NULL; cur = cur->next) { if (only_node && cur->type != XML_ELEMENT_NODE) { continue; } return Rf_ScalarLogical(true); } return Rf_ScalarLogical(false); END_CPP } // [[export]] extern "C" SEXP node_parents(SEXP node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); std::vector out; for(xmlNode* cur = node->parent; cur != NULL; cur = cur->parent) { if (cur->type != XML_ELEMENT_NODE) continue; out.push_back(cur); } return asList(out); END_CPP } // [[export]] extern "C" SEXP node_siblings(SEXP node_sxp, SEXP only_node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); bool only_node = LOGICAL(only_node_sxp)[0]; std::vector out; xmlNode* parent = node->parent; if (parent == NULL) return Rf_allocVector(VECSXP, 0); for(xmlNode* cur = parent->xmlChildrenNode; cur != NULL; cur = cur->next) { if (cur == node) { continue; } if (only_node && cur->type != XML_ELEMENT_NODE) { continue; } out.push_back(cur); } return asList(out); END_CPP } // [[export]] extern "C" SEXP node_parent(SEXP node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); if (node->parent == NULL) { Rf_error("Parent does not exist"); } XPtrNode out(node->parent); return SEXP(out); END_CPP } // [[export]] extern "C" SEXP node_path(SEXP node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); return Rf_ScalarString(Xml2String(xmlGetNodePath(node.checked_get())).asRString()); END_CPP } // [[export]] extern "C" SEXP nodes_duplicated(SEXP nodes) { BEGIN_CPP std::set seen; int n = Rf_xlength(nodes); SEXP out = PROTECT(Rf_allocVector(LGLSXP, n)); for (int i = 0; i < n; ++i) { bool result; SEXP cur = VECTOR_ELT(nodes, i); if (Rf_inherits(cur, "xml_node")) { XPtrNode node(VECTOR_ELT(cur, 0)); result = !seen.insert(node.checked_get()).second; } else if (Rf_inherits(cur, "xml_missing")) { result = false; } else { XPtrNode node(cur); result = !seen.insert(node.checked_get()).second; } LOGICAL(out)[i] = result; } UNPROTECT(1); return out; END_CPP } // [[export]] extern "C" SEXP node_type(SEXP node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); return Rf_ScalarInteger(node->type); END_CPP } // [[export]] extern "C" SEXP node_copy(SEXP node_sxp) { BEGIN_CPP XPtrNode node(node_sxp); XPtrNode copy(xmlCopyNode(node.checked_get(), 1)); return SEXP(copy); END_CPP } // [[export]] extern "C" SEXP node_set_content(SEXP node_sxp, SEXP content) { BEGIN_CPP XPtrNode node(node_sxp); xmlNodeSetContentLen(node.checked_get(), asXmlChar(content), Rf_xlength(STRING_ELT(content, 0))); return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_append_content(SEXP node_sxp, SEXP content) { BEGIN_CPP XPtrNode node(node_sxp); xmlNodeAddContentLen(node.checked_get(), asXmlChar(content), Rf_xlength(STRING_ELT(content, 0))); return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_new_text(SEXP node_sxp, SEXP content) { BEGIN_CPP XPtrNode node(node_sxp); xmlAddChild(node.checked_get(), xmlNewTextLen(asXmlChar(content), Rf_xlength(STRING_ELT(content, 0)))); return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_append_child(SEXP parent_sxp, SEXP cur_sxp) { BEGIN_CPP XPtrNode parent(parent_sxp); XPtrNode cur(cur_sxp); XPtrNode out(xmlAddChild(parent.checked_get(), cur.checked_get())); return SEXP(out); END_CPP } // [[export]] extern "C" SEXP node_prepend_child(SEXP parent_sxp, SEXP cur_sxp) { BEGIN_CPP XPtrNode parent(parent_sxp); XPtrNode cur(cur_sxp); XPtrNode out(xmlAddPrevSibling(parent.checked_get()->children, cur.checked_get())); return SEXP(out); END_CPP } // Previous sibling // [[export]] extern "C" SEXP node_prepend_sibling(SEXP cur_sxp, SEXP elem_sxp) { BEGIN_CPP XPtrNode cur(cur_sxp); XPtrNode elem(elem_sxp); XPtrNode out(xmlAddPrevSibling(cur.checked_get(), elem.checked_get())); return SEXP(out); END_CPP } // Append sibling // [[export]] extern "C" SEXP node_append_sibling(SEXP cur_sxp, SEXP elem_sxp) { BEGIN_CPP XPtrNode cur(cur_sxp); XPtrNode elem(elem_sxp); XPtrNode out(xmlAddNextSibling(cur.checked_get(), elem.checked_get())); return SEXP(out); END_CPP } // Replace node // [[export]] extern "C" SEXP node_replace(SEXP old_sxp, SEXP cur_sxp) { BEGIN_CPP XPtrNode old(old_sxp); XPtrNode cur(cur_sxp); XPtrNode out(xmlReplaceNode(old.checked_get(), cur.checked_get())); return SEXP(out); END_CPP } // [[export]] extern "C" SEXP node_remove(SEXP node_sxp, SEXP free_sxp) { BEGIN_CPP XPtrNode node(node_sxp); bool free = LOGICAL(free_sxp)[0]; xmlUnlinkNode(node.checked_get()); if (free) { xmlFreeNode(node.checked_get()); } return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_new(SEXP name) { BEGIN_CPP XPtrNode node(xmlNewNode(NULL, asXmlChar(name))); return SEXP(node); END_CPP } // [[export]] extern "C" SEXP node_cdata_new(SEXP doc_sxp, SEXP content_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); XPtrNode node(xmlNewCDataBlock(doc.checked_get(), asXmlChar(content_sxp), Rf_xlength(STRING_ELT(content_sxp, 0)))); return SEXP(node); END_CPP } // [[export]] extern "C" SEXP node_comment_new(SEXP content) { BEGIN_CPP XPtrNode node(xmlNewComment(asXmlChar(content))); return SEXP(node); END_CPP } // [[export]] extern "C" SEXP node_new_ns(SEXP name, SEXP ns_sxp) { BEGIN_CPP XPtrNs ns(ns_sxp); XPtrNode node(xmlNewNode(ns.checked_get(), asXmlChar(name))); return SEXP(node); END_CPP } // [[export]] extern "C" SEXP node_set_namespace_uri(SEXP doc_sxp, SEXP node_sxp, SEXP uri) { BEGIN_CPP XPtrDoc doc(doc_sxp); XPtrNode node(node_sxp); xmlNsPtr ns = xmlSearchNsByHref(doc.checked_get(), node.checked_get(), asXmlChar(uri)); xmlSetNs(node.checked_get(), ns); return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_set_namespace_prefix(SEXP doc_sxp, SEXP node_sxp, SEXP prefix_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); XPtrNode node(node_sxp); xmlNsPtr ns = NULL; if (Rf_xlength(STRING_ELT(prefix_sxp, 0)) == 0) { ns = xmlSearchNs(doc.checked_get(), node.checked_get(), NULL); } else { ns = xmlSearchNs(doc.checked_get(), node.checked_get(), asXmlChar(prefix_sxp)); } xmlSetNs(node.checked_get(), ns); return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_new_dtd(SEXP doc_sxp, SEXP name_sxp, SEXP eid_sxp, SEXP sid_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); std::string name(CHAR(STRING_ELT(name_sxp, 0))); std::string eid(CHAR(STRING_ELT(eid_sxp, 0))); std::string sid(CHAR(STRING_ELT(sid_sxp, 0))); xmlDtdPtr dtd = xmlNewDtd(doc, name == "" ? NULL : asXmlChar(name), eid == "" ? NULL : asXmlChar(eid), sid == "" ? NULL : asXmlChar(sid)); xmlAddChild(reinterpret_cast(doc.checked_get()), reinterpret_cast(dtd)); return R_NilValue; END_CPP } xml2/src/xml2_init.cpp0000644000176200001440000000240413640647023014341 0ustar liggesusers#define R_NO_REMAP #include #undef R_NO_REMAP #include #include #include #include #include #include #include "xml2_utils.h" void handleStructuredError(void* userData, xmlError* error) { BEGIN_CPP std::string message = std::string(error->message); message.resize(message.size() - 1); // trim off trailing newline if (error->level <= 2) { Rf_warning("%s [%i]", message.c_str(), (int) error->code); } else { Rf_error("%s [%i]", message.c_str(), (int) error->code); } END_CPP } void handleGenericError(void *ctx, const char *fmt, ...) { char buffer[BUFSIZ]; va_list arg; if (fmt == NULL) fmt = "(null)"; va_start(arg, fmt); vsnprintf(buffer, BUFSIZ, fmt, arg); Rf_error(buffer); } // [[export]] extern "C" SEXP init_libxml2() { // Check that header and libs are compatible LIBXML_TEST_VERSION xmlInitParser(); xmlSetStructuredErrorFunc(NULL, handleStructuredError); xmlSetGenericErrorFunc(NULL, handleGenericError); return R_NilValue; } extern "C" { void R_unload_xml2(DllInfo *info) { xmlCleanupParser(); } } // [[export]] extern "C" SEXP libxml2_version_(){ return Rf_mkString(LIBXML_DOTTED_VERSION); } xml2/src/xml2_output.cpp0000644000176200001440000001442713640650407014746 0ustar liggesusers#include #include "connection.h" #include #include #include #include "xml2_types.h" #include "xml2_utils.h" /* * * * * Author: Daniel Veillard * Date: Thu Sep 25 14:31:40 2008 +0000 * https://github.com/GNOME/libxml2/commit/856d92818bda07549a532d6fb16f323a94e0c39a * * include/libxml/xmlsave.h xmlsave.c: new options to serialize * as XML/HTML/XHTML and restore old entry point behaviours * Daniel */ #if defined(LIBXML_VERSION) && (LIBXML_VERSION >= 20704) #define HAS_SAVE_HTML #endif /* * * * * Author: Adam Spragg * Date: Wed Nov 3 15:33:40 2010 +0100 * https://github.com/GNOME/libxml2/commit/d2e62311cd15651e68f921167c7fcf05b19378f9 * * Add xmlSaveOption XML_SAVE_WSNONSIG */ #if defined(LIBXML_VERSION) && (LIBXML_VERSION >= 20708) #define HAS_SAVE_WSNONSIG #endif typedef struct { const char* name; const char* description; int value; } xml_save_def; // [[export]] extern "C" SEXP xml_save_options_() { static const xml_save_def entries[] = { {"format", "Format output", XML_SAVE_FORMAT}, {"no_declaration", "Drop the XML declaration", XML_SAVE_NO_DECL}, {"no_empty_tags", "Remove empty tags", XML_SAVE_NO_EMPTY}, #ifdef HAS_SAVE_HTML {"no_xhtml", "Disable XHTML1 rules", XML_SAVE_NO_XHTML}, {"require_xhtml", "Force XHTML rules", XML_SAVE_XHTML}, {"as_xml", "Force XML output", XML_SAVE_AS_XML}, {"as_html", "Force HTML output", XML_SAVE_AS_HTML}, #endif #ifdef HAS_SAVE_WSNONSIG {"format_whitespace", "Format with non-significant whitespace", XML_SAVE_WSNONSIG}, #endif {NULL, NULL, 0} }; // First figure out size, seems like there would be a way for the compiler to // do this, but I don't know it. R_xlen_t n = 0; while(entries[n].name != NULL) { ++n; } SEXP names = PROTECT(Rf_allocVector(STRSXP, n)); SEXP descriptions = PROTECT(Rf_allocVector(STRSXP, n)); SEXP values = PROTECT(Rf_allocVector(INTSXP, n)); for (R_xlen_t i = 0;i < n; ++i) { SET_STRING_ELT(names, i, Rf_mkChar(entries[i].name)); SET_STRING_ELT(descriptions, i, Rf_mkChar(entries[i].description)); INTEGER(values)[i] = entries[i].value; } Rf_setAttrib(values, R_NamesSymbol, names); Rf_setAttrib(values, Rf_install("descriptions"), descriptions); UNPROTECT(3); return values; } int xml_write_callback(SEXP con, const char * buffer, int len) { size_t write_size; if ((write_size = R_WriteConnection(con, (void *) buffer, len)) != static_cast(len)) { Rf_error("write failed, expected %l, got %l", len, write_size); } return write_size; } // [[export]] extern "C" SEXP doc_write_file(SEXP doc_sxp, SEXP path_sxp, SEXP encoding_sxp, SEXP options_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); const char* path = CHAR(STRING_ELT(path_sxp, 0)); const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); int options = INTEGER(options_sxp)[0]; xmlSaveCtxtPtr savectx = xmlSaveToFilename( path, encoding, options); xmlSaveDoc(savectx, doc.checked_get()); if (xmlSaveClose(savectx) == -1) { Rf_error("Error closing file"); } return R_NilValue; END_CPP } // [[export]] extern "C" SEXP doc_write_connection(SEXP doc_sxp, SEXP connection, SEXP encoding_sxp, SEXP options_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); int options = INTEGER(options_sxp)[0]; SEXP con = R_GetConnection(connection); xmlSaveCtxtPtr savectx = xmlSaveToIO( reinterpret_cast(xml_write_callback), NULL, con, encoding, options); xmlSaveDoc(savectx, doc.checked_get()); if (xmlSaveClose(savectx) == -1) { Rf_error("Error closing connection"); } return R_NilValue; END_CPP } // [[export]] extern "C" SEXP doc_write_character(SEXP doc_sxp, SEXP encoding_sxp, SEXP options_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); int options = INTEGER(options_sxp)[0]; xmlBufferPtr buffer = xmlBufferCreate(); xmlSaveCtxtPtr savectx = xmlSaveToBuffer( buffer, encoding, options); xmlSaveDoc(savectx, doc.checked_get()); if (xmlSaveClose(savectx) == -1) { xmlFree(buffer); Rf_error("Error writing to buffer"); } SEXP out = PROTECT(Rf_allocVector(STRSXP, 1)); SET_STRING_ELT(out, 0, Xml2String(buffer->content).asRString()); xmlFree(buffer); UNPROTECT(1); return out; END_CPP } // [[export]] extern "C" SEXP node_write_file(SEXP node_sxp, SEXP path_sxp, SEXP encoding_sxp, SEXP options_sxp) { BEGIN_CPP XPtrNode node(node_sxp); const char* path = CHAR(STRING_ELT(path_sxp, 0)); const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); int options = INTEGER(options_sxp)[0]; xmlSaveCtxtPtr savectx = xmlSaveToFilename( path, encoding, options); xmlSaveTree(savectx, node.checked_get()); if (xmlSaveClose(savectx) == -1) { Rf_error("Error closing file"); } return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_write_connection(SEXP node_sxp, SEXP connection, SEXP encoding_sxp, SEXP options_sxp) { BEGIN_CPP XPtrNode node(node_sxp); SEXP con = R_GetConnection(connection); const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); int options = INTEGER(options_sxp)[0]; xmlSaveCtxtPtr savectx = xmlSaveToIO( (xmlOutputWriteCallback)xml_write_callback, NULL, con, encoding, options); xmlSaveTree(savectx, node.checked_get()); if (xmlSaveClose(savectx) == -1) { Rf_error("Error closing connection"); } return R_NilValue; END_CPP } // [[export]] extern "C" SEXP node_write_character(SEXP node_sxp, SEXP encoding_sxp, SEXP options_sxp) { BEGIN_CPP XPtrNode node(node_sxp); const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); int options = INTEGER(options_sxp)[0]; xmlBufferPtr buffer = xmlBufferCreate(); xmlSaveCtxtPtr savectx = xmlSaveToBuffer( buffer, encoding, options); xmlSaveTree(savectx, node.checked_get()); if (xmlSaveClose(savectx) == -1) { xmlFree(buffer); Rf_error("Error writing to buffer"); } SEXP out = PROTECT(Rf_ScalarString(Xml2String(buffer->content).asRString())); xmlFree(buffer); UNPROTECT(1); return out; END_CPP } xml2/src/xml2_doc.cpp0000644000176200001440000001577413642155343014162 0ustar liggesusers#include #include #include #include "xml2_types.h" #include "xml2_utils.h" #include // [[export]] extern "C" SEXP xml_parse_options_() { #if defined(LIBXML_VERSION) && (LIBXML_VERSION >= 20700) #define HAS_OLD10 #define HAS_NOBASEFIX #define HAS_HUGE #define HAS_OLDSAX #endif /* * * * Author: Daniel Veillard * Date: Mon May 16 16:03:50 2011 +0800 * https://github.com/GNOME/libxml2/commit/c62efc847c836d4c4f1aea08c68cd93bd342b9f4 * * Add options to ignore the internal encoding */ #if defined(LIBXML_VERSION) && (LIBXML_VERSION >= 20800) #define HAS_IGNORE_ENC #endif /* * * * Author: Daniel Veillard * Date: Mon Aug 13 12:41:33 2012 +0800 * https://github.com/GNOME/libxml2/commit/968a03a2e54f5bcf53089f5e3c8f790dbe0bf824 * * Add support for big line numbers in error reporting */ #if defined(LIBXML_VERSION) && (LIBXML_VERSION >= 20900) #define HAS_BIG_LINES #endif const char * names[] = { "RECOVER", "NOENT", "DTDLOAD", "DTDATTR", "DTDVALID", "NOERROR", "NOWARNING", "PEDANTIC", "NOBLANKS", "SAX1", "XINCLUDE", "NONET", "NODICT", "NSCLEAN", "NOCDATA", "NOXINCNODE", "COMPACT", #ifdef HAS_OLD10 "OLD10", #endif #ifdef HAS_NOBASEFIX "NOBASEFIX", #endif #ifdef HAS_HUGE "HUGE", #endif #ifdef HAS_OLDSAX "OLDSAX", #endif #ifdef HAS_IGNORE_ENC "IGNORE_ENC", #endif #ifdef HAS_BIG_LINES "BIG_LINES", #endif }; const int values[] = { XML_PARSE_RECOVER, XML_PARSE_NOENT, XML_PARSE_DTDLOAD, XML_PARSE_DTDATTR, XML_PARSE_DTDVALID, XML_PARSE_NOERROR, XML_PARSE_NOWARNING, XML_PARSE_PEDANTIC, XML_PARSE_NOBLANKS, XML_PARSE_SAX1, XML_PARSE_XINCLUDE, XML_PARSE_NONET, XML_PARSE_NODICT, XML_PARSE_NSCLEAN, XML_PARSE_NOCDATA, XML_PARSE_NOXINCNODE, XML_PARSE_COMPACT, #ifdef HAS_OLD10 XML_PARSE_OLD10, #endif #ifdef HAS_NOBASEFIX XML_PARSE_NOBASEFIX, #endif #ifdef HAS_HUGE XML_PARSE_HUGE, #endif #ifdef HAS_OLDSAX XML_PARSE_OLDSAX, #endif #ifdef HAS_IGNORE_ENC XML_PARSE_IGNORE_ENC, #endif #ifdef HAS_BIG_LINES XML_PARSE_BIG_LINES, #endif }; const char * descriptions[] = { "recover on errors", "substitute entities", "load the external subset", "default DTD attributes", "validate with the DTD", "suppress error reports", "suppress warning reports", "pedantic error reporting", "remove blank nodes", "use the SAX1 interface internally", "Implement XInclude substitition", "Forbid network access", "Do not reuse the context dictionary", "remove redundant namespaces declarations", "merge CDATA as text nodes", "do not generate XINCLUDE START/END nodes", "compact small text nodes; no modification of the tree allowed afterwards (will possibly crash if you try to modify the tree)", #ifdef HAS_OLD10 "parse using XML-1.0 before update 5", #endif #ifdef HAS_NOBASEFIX "do not fixup XINCLUDE xml:base uris", #endif #ifdef HAS_HUGE "relax any hardcoded limit from the parser", #endif #ifdef HAS_OLDSAX "parse using SAX2 interface before 2.7.0", #endif #ifdef HAS_IGNORE_ENC "ignore internal document encoding hint", #endif #ifdef HAS_BIG_LINES "Store big lines numbers in text PSVI field", #endif }; size_t size = sizeof(values) / sizeof(values[0]); SEXP out_values = PROTECT(Rf_allocVector(INTSXP, size)); SEXP out_names = PROTECT(Rf_allocVector(STRSXP, size)); SEXP out_descriptions = PROTECT(Rf_allocVector(STRSXP, size)); for (size_t i = 0; i < size; ++i) { INTEGER(out_values)[i] = values[i]; SET_STRING_ELT(out_names, i, Rf_mkChar(names[i])); SET_STRING_ELT(out_descriptions, i, Rf_mkChar(descriptions[i])); } Rf_setAttrib(out_values, R_NamesSymbol, out_names); Rf_setAttrib(out_values, Rf_install("descriptions"), out_descriptions); UNPROTECT(3); return out_values; #undef HAS_OLD10 #undef HAS_NOBASEFIX #undef HAS_HUGE #undef HAS_OLDSAX #undef HAS_BIG_LINES #undef HAS_IGNORE_ENC } // [[export]] extern "C" SEXP doc_parse_file( SEXP path_sxp, SEXP encoding_sxp, SEXP as_html_sxp, SEXP options_sxp) { const char* path = CHAR(STRING_ELT(path_sxp, 0)); const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); bool as_html = LOGICAL(as_html_sxp)[0]; int options = INTEGER(options_sxp)[0]; xmlDoc* pDoc; if (as_html) { pDoc = htmlReadFile( path, encoding[0] == '\0' ? NULL : encoding, options ); } else { pDoc = xmlReadFile( path, encoding[0] == '\0' ? NULL : encoding, options ); } if (pDoc == NULL) { Rf_error("Failed to parse %s", path); } return SEXP(XPtrDoc(pDoc)); } // [[export]] extern "C" SEXP doc_parse_raw( SEXP x, SEXP encoding_sxp, SEXP base_url_sxp, SEXP as_html_sxp, SEXP options_sxp) { BEGIN_CPP std::string encoding(CHAR(STRING_ELT(encoding_sxp, 0))); std::string base_url(CHAR(STRING_ELT(encoding_sxp, 0))); bool as_html = LOGICAL(as_html_sxp)[0]; int options = INTEGER(options_sxp)[0]; xmlDoc* pDoc; if (as_html) { pDoc = htmlReadMemory( (const char *) RAW(x), Rf_length(x), base_url == "" ? NULL : base_url.c_str(), encoding == "" ? NULL : encoding.c_str(), options ); } else { pDoc = xmlReadMemory( (const char *) RAW(x), Rf_length(x), base_url == "" ? NULL : base_url.c_str(), encoding == "" ? NULL : encoding.c_str(), options ); } if (pDoc == NULL) { Rf_error("Failed to parse text"); } return SEXP(XPtrDoc(pDoc)); END_CPP } // [[export]] extern "C" SEXP doc_root(SEXP x) { BEGIN_CPP XPtrDoc doc(x); XPtrNode node(xmlDocGetRootElement(doc.checked_get())); return SEXP(node); END_CPP } // [[export]] extern "C" SEXP doc_has_root(SEXP x_sxp) { BEGIN_CPP XPtrDoc x(x_sxp); return Rf_ScalarLogical(xmlDocGetRootElement(x.get()) != NULL); END_CPP } // [[export]] extern "C" SEXP doc_url(SEXP doc_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); if (doc->URL == NULL) { return NA_STRING; } SEXP out = PROTECT(Rf_allocVector(STRSXP, 1)); SET_STRING_ELT(out, 0, Rf_mkCharCE((const char*) doc->URL, CE_UTF8)); UNPROTECT(1); return out; END_CPP } // [[export]] extern "C" SEXP doc_new(SEXP version_sxp, SEXP encoding_sxp) { const char* encoding = CHAR(STRING_ELT(encoding_sxp, 0)); BEGIN_CPP XPtrDoc x(xmlNewDoc(asXmlChar(version_sxp))); xmlCharEncodingHandlerPtr p = xmlFindCharEncodingHandler(encoding); x->encoding = xmlStrdup(reinterpret_cast(p->name)); return SEXP(x); END_CPP } // [[export]] extern "C" SEXP doc_set_root(SEXP doc_sxp, SEXP root_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); XPtrNode root(root_sxp); XPtrNode out(xmlDocSetRootElement(doc, root)); return SEXP(out); END_CPP } // [[export]] extern "C" SEXP doc_is_html(SEXP doc_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); return Rf_ScalarLogical(doc->properties & XML_DOC_HTML); END_CPP } xml2/src/init.c0000644000176200001440000001703713637645657013070 0ustar liggesusers#include #include #include // for NULL #include /* FIXME: Check these declarations against the C/Fortran source code. */ /* .Call calls */ extern SEXP doc_has_root(SEXP); extern SEXP doc_is_html(SEXP); extern SEXP doc_namespaces(SEXP); extern SEXP doc_new(SEXP, SEXP); extern SEXP doc_parse_file(SEXP, SEXP, SEXP, SEXP); extern SEXP doc_parse_raw(SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP doc_root(SEXP); extern SEXP doc_set_root(SEXP, SEXP); extern SEXP doc_url(SEXP); extern SEXP doc_validate(SEXP, SEXP); extern SEXP doc_write_character(SEXP, SEXP, SEXP); extern SEXP doc_write_connection(SEXP, SEXP, SEXP, SEXP); extern SEXP doc_write_file(SEXP, SEXP, SEXP, SEXP); extern SEXP init_libxml2(); extern SEXP libxml2_version_(); extern SEXP node_append_child(SEXP, SEXP); extern SEXP node_append_content(SEXP, SEXP); extern SEXP node_append_sibling(SEXP, SEXP); extern SEXP node_attr(SEXP, SEXP, SEXP, SEXP); extern SEXP node_attrs(SEXP, SEXP); extern SEXP node_cdata_new(SEXP, SEXP); extern SEXP node_children(SEXP, SEXP); extern SEXP node_comment_new(SEXP); extern SEXP node_copy(SEXP); extern SEXP node_has_children(SEXP, SEXP); extern SEXP node_length(SEXP, SEXP); extern SEXP node_name(SEXP, SEXP); extern SEXP node_new(SEXP); extern SEXP node_new_dtd(SEXP, SEXP, SEXP, SEXP); extern SEXP node_new_ns(SEXP, SEXP); extern SEXP node_new_text(SEXP, SEXP); extern SEXP node_parent(SEXP); extern SEXP node_parents(SEXP); extern SEXP node_path(SEXP); extern SEXP node_prepend_child(SEXP, SEXP); extern SEXP node_prepend_sibling(SEXP, SEXP); extern SEXP node_remove(SEXP, SEXP); extern SEXP node_remove_attr(SEXP, SEXP, SEXP); extern SEXP node_replace(SEXP, SEXP); extern SEXP node_set_attr(SEXP, SEXP, SEXP, SEXP); extern SEXP node_set_content(SEXP, SEXP); extern SEXP node_set_name(SEXP, SEXP); extern SEXP node_set_namespace_prefix(SEXP, SEXP, SEXP); extern SEXP node_set_namespace_uri(SEXP, SEXP, SEXP); extern SEXP node_siblings(SEXP, SEXP); extern SEXP node_text(SEXP); extern SEXP node_type(SEXP); extern SEXP node_write_character(SEXP, SEXP, SEXP); extern SEXP node_write_connection(SEXP, SEXP, SEXP, SEXP); extern SEXP node_write_file(SEXP, SEXP, SEXP, SEXP); extern SEXP nodes_duplicated(SEXP); extern SEXP ns_lookup(SEXP, SEXP, SEXP); extern SEXP ns_lookup_uri(SEXP, SEXP, SEXP); extern SEXP read_connection_(SEXP, SEXP); extern SEXP unique_ns(SEXP); extern SEXP url_absolute_(SEXP, SEXP); extern SEXP url_escape_(SEXP, SEXP); extern SEXP url_parse_(SEXP); extern SEXP url_relative_(SEXP, SEXP); extern SEXP url_unescape_(SEXP); extern SEXP xml_parse_options_(); extern SEXP xml_save_options_(); extern SEXP xpath_search(SEXP, SEXP, SEXP, SEXP, SEXP); static const R_CallMethodDef CallEntries[] = { {"doc_has_root", (DL_FUNC) &doc_has_root, 1}, {"doc_is_html", (DL_FUNC) &doc_is_html, 1}, {"doc_namespaces", (DL_FUNC) &doc_namespaces, 1}, {"doc_new", (DL_FUNC) &doc_new, 2}, {"doc_parse_file", (DL_FUNC) &doc_parse_file, 4}, {"doc_parse_raw", (DL_FUNC) &doc_parse_raw, 5}, {"doc_root", (DL_FUNC) &doc_root, 1}, {"doc_set_root", (DL_FUNC) &doc_set_root, 2}, {"doc_url", (DL_FUNC) &doc_url, 1}, {"doc_validate", (DL_FUNC) &doc_validate, 2}, {"doc_write_character", (DL_FUNC) &doc_write_character, 3}, {"doc_write_connection", (DL_FUNC) &doc_write_connection, 4}, {"doc_write_file", (DL_FUNC) &doc_write_file, 4}, {"init_libxml2", (DL_FUNC) &init_libxml2, 0}, {"libxml2_version_", (DL_FUNC) &libxml2_version_, 0}, {"node_append_child", (DL_FUNC) &node_append_child, 2}, {"node_append_content", (DL_FUNC) &node_append_content, 2}, {"node_append_sibling", (DL_FUNC) &node_append_sibling, 2}, {"node_attr", (DL_FUNC) &node_attr, 4}, {"node_attrs", (DL_FUNC) &node_attrs, 2}, {"node_cdata_new", (DL_FUNC) &node_cdata_new, 2}, {"node_children", (DL_FUNC) &node_children, 2}, {"node_comment_new", (DL_FUNC) &node_comment_new, 1}, {"node_copy", (DL_FUNC) &node_copy, 1}, {"node_has_children", (DL_FUNC) &node_has_children, 2}, {"node_length", (DL_FUNC) &node_length, 2}, {"node_name", (DL_FUNC) &node_name, 2}, {"node_new", (DL_FUNC) &node_new, 1}, {"node_new_dtd", (DL_FUNC) &node_new_dtd, 4}, {"node_new_ns", (DL_FUNC) &node_new_ns, 2}, {"node_new_text", (DL_FUNC) &node_new_text, 2}, {"node_parent", (DL_FUNC) &node_parent, 1}, {"node_parents", (DL_FUNC) &node_parents, 1}, {"node_path", (DL_FUNC) &node_path, 1}, {"node_prepend_child", (DL_FUNC) &node_prepend_child, 2}, {"node_prepend_sibling", (DL_FUNC) &node_prepend_sibling, 2}, {"node_remove", (DL_FUNC) &node_remove, 2}, {"node_remove_attr", (DL_FUNC) &node_remove_attr, 3}, {"node_replace", (DL_FUNC) &node_replace, 2}, {"node_set_attr", (DL_FUNC) &node_set_attr, 4}, {"node_set_content", (DL_FUNC) &node_set_content, 2}, {"node_set_name", (DL_FUNC) &node_set_name, 2}, {"node_set_namespace_prefix", (DL_FUNC) &node_set_namespace_prefix, 3}, {"node_set_namespace_uri", (DL_FUNC) &node_set_namespace_uri, 3}, {"node_siblings", (DL_FUNC) &node_siblings, 2}, {"node_text", (DL_FUNC) &node_text, 1}, {"node_type", (DL_FUNC) &node_type, 1}, {"node_write_character", (DL_FUNC) &node_write_character, 3}, {"node_write_connection", (DL_FUNC) &node_write_connection, 4}, {"node_write_file", (DL_FUNC) &node_write_file, 4}, {"nodes_duplicated", (DL_FUNC) &nodes_duplicated, 1}, {"ns_lookup", (DL_FUNC) &ns_lookup, 3}, {"ns_lookup_uri", (DL_FUNC) &ns_lookup_uri, 3}, {"read_connection_", (DL_FUNC) &read_connection_, 2}, {"unique_ns", (DL_FUNC) &unique_ns, 1}, {"url_absolute_", (DL_FUNC) &url_absolute_, 2}, {"url_escape_", (DL_FUNC) &url_escape_, 2}, {"url_parse_", (DL_FUNC) &url_parse_, 1}, {"url_relative_", (DL_FUNC) &url_relative_, 2}, {"url_unescape_", (DL_FUNC) &url_unescape_, 1}, {"xml_parse_options_", (DL_FUNC) &xml_parse_options_, 0}, {"xml_save_options_", (DL_FUNC) &xml_save_options_, 0}, {"xpath_search", (DL_FUNC) &xpath_search, 5}, {NULL, NULL, 0} }; void R_init_xml2(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } xml2/src/xml2_xpath.cpp0000644000176200001440000000645013637646422014537 0ustar liggesusers#include #include #include #include #include "xml2_types.h" #include class XmlSeeker { xmlXPathContext* context_; xmlXPathObject* result_; XPtrDoc doc_; public: XmlSeeker(XPtrDoc doc, xmlNode* node) : result_(NULL), doc_(doc) { context_ = xmlXPathNewContext(doc.checked_get()); // Set context to current node context_->node = node; } void registerNamespace(SEXP nsMap) { R_xlen_t n = Rf_xlength(nsMap); if (n == 0) { return; } SEXP prefix = Rf_getAttrib(nsMap, R_NamesSymbol); for (int i = 0; i < n; ++i) { xmlChar* prefixI = (xmlChar*) CHAR(STRING_ELT(prefix, i)); xmlChar* urlI = (xmlChar*) CHAR(STRING_ELT(nsMap, i)); if (xmlXPathRegisterNs(context_, prefixI, urlI) != 0) Rf_error("Failed to register namespace (%s <-> %s)", prefixI, urlI); } } SEXP search(const char* xpath, int num_results) { result_ = xmlXPathEval((const xmlChar*)xpath, context_); if (result_ == NULL) { SEXP ret = PROTECT(Rf_allocVector(VECSXP, 0)); Rf_setAttrib(ret, R_ClassSymbol, Rf_mkString("xml_missing")); UNPROTECT(1); return ret; } switch (result_->type) { case XPATH_NODESET: { xmlNodeSet* nodes = result_->nodesetval; if (nodes == NULL || nodes->nodeNr == 0) { SEXP ret = PROTECT(Rf_allocVector(VECSXP, 0)); Rf_setAttrib(ret, R_ClassSymbol, Rf_mkString("xml_missing")); UNPROTECT(1); return ret; } int n = std::min(result_->nodesetval->nodeNr, num_results); SEXP out = PROTECT(Rf_allocVector(VECSXP, n)); SEXP names = PROTECT(Rf_allocVector(STRSXP, 2)); SET_STRING_ELT(names, 0, Rf_mkChar("node")); SET_STRING_ELT(names, 1, Rf_mkChar("doc")); for (int i = 0; i < n; i++) { SEXP ret = PROTECT(Rf_allocVector(VECSXP, 2)); SET_VECTOR_ELT(ret, 0, XPtrNode(nodes->nodeTab[i])); SET_VECTOR_ELT(ret, 1, doc_); Rf_setAttrib(ret, R_NamesSymbol, names); Rf_setAttrib(ret, R_ClassSymbol, Rf_mkString("xml_node")); SET_VECTOR_ELT(out, i, ret); UNPROTECT(1); } UNPROTECT(2); return out; } case XPATH_NUMBER: { return Rf_ScalarReal(result_->floatval); } case XPATH_BOOLEAN: { return Rf_ScalarLogical(result_->boolval); } case XPATH_STRING: { return Rf_ScalarString(Rf_mkCharCE((char *) result_->stringval, CE_UTF8)); } default: Rf_error("XPath result type: %d not supported", result_->type); } return R_NilValue; } ~XmlSeeker() { try { xmlXPathFreeContext(context_); if (result_ != NULL) xmlXPathFreeObject(result_); } catch (...) {} } }; // [[export]] extern "C" SEXP xpath_search(SEXP node_sxp, SEXP doc_sxp, SEXP xpath_sxp, SEXP nsMap_sxp, SEXP num_results_sxp) { XPtrNode node(node_sxp); XPtrDoc doc(doc_sxp); const char* xpath = CHAR(STRING_ELT(xpath_sxp, 0)); double num_results = REAL(num_results_sxp)[0]; if (num_results == R_PosInf) { num_results = INT_MAX; } XmlSeeker seeker(doc, node.checked_get()); seeker.registerNamespace(nsMap_sxp); return seeker.search(xpath, num_results); } xml2/src/connection.h0000644000176200001440000000121613637645657014261 0ustar liggesusers#pragma once #include #include #include SEXP read_bin(SEXP con, size_t bytes = 64 * 1024); SEXP write_bin(SEXP data, SEXP con); inline SEXP R_GetConnection(SEXP con) { return con; } inline size_t R_ReadConnection(SEXP con, void* buf, size_t n) { SEXP res = PROTECT(read_bin(con, n)); R_xlen_t size = Rf_xlength(res); memcpy(buf, RAW(res), size); UNPROTECT(1); return Rf_xlength(res); } inline size_t R_WriteConnection(SEXP con, void* buf, size_t n) { SEXP payload = PROTECT(Rf_allocVector(RAWSXP, n)); memcpy(RAW(payload), buf, n); write_bin(payload, con); UNPROTECT(1); return n; } xml2/src/xml2_utils.h0000644000176200001440000000745413640704660014216 0ustar liggesusers#ifndef __XML2_XML_UTILS__ #define __XML2_XML_UTILS__ #include #include #include #include inline const xmlChar* asXmlChar(std::string const& x) { return (const xmlChar*) x.c_str(); } inline const xmlChar* asXmlChar(SEXP x, int n = 0) { return (const xmlChar*) CHAR(STRING_ELT(x, n)); } #define BEGIN_CPP try { #define END_CPP \ } \ catch (std::exception & e) { \ Rf_error("C++ exception: %s", e.what()); \ } // If we are using C++11 disallow moves #if __cplusplus >= 201103L void asXmlChar(std::string&&) = delete; #endif // ---------------------------------------------------------------------------- // A wrapper around xmlChar* that frees memory if necessary class Xml2String { xmlChar* string_; bool free_; public: Xml2String(): string_(NULL), free_(false) {} Xml2String(xmlChar* string): string_(string), free_(true) {} // Pointers into structs are const, so don't need to be freed Xml2String(const xmlChar* string): string_((xmlChar*) string), free_(false) {} // Some strings are regular strings Xml2String(const char* string): string_((xmlChar*) string), free_(false) {} ~Xml2String() { try { if (free_ && string_ != NULL) xmlFree(string_); } catch (...) {} } std::string asStdString(std::string missing = "") { if (string_ == NULL) return missing; return std::string((char*) string_); } SEXP asRString(SEXP missing = NA_STRING) { if (string_ == NULL) return missing; return Rf_mkCharCE((char*) string_, CE_UTF8); }; }; // ---------------------------------------------------------------------------- // A wrapper around a pair of character vectors used to namespaces to prefixes class NsMap { // We only store the index to avoid duplicating the data typedef std::multimap prefix2url_t; prefix2url_t prefix2url; public: NsMap() { } // Initialise from an existing STRSXP NsMap(SEXP x) { SEXP names = Rf_getAttrib(x, R_NamesSymbol); for (R_len_t i = 0; i < Rf_xlength(x); ++i) { add(std::string(CHAR(STRING_ELT(names, i))), std::string(CHAR(STRING_ELT(x, i)))); } } bool hasPrefix(const std::string& prefix) { return prefix2url.find(prefix) != prefix2url.end(); } std::string findUrl(const std::string& prefix) { prefix2url_t::const_iterator it = prefix2url.find(prefix); if (it != prefix2url.end()) { return it->second; } Rf_error("Couldn't find url for prefix %s", prefix.c_str()); return std::string(); } std::string findPrefix(const std::string& url) { for (prefix2url_t::const_iterator it = prefix2url.begin(); it != prefix2url.end(); ++it) { if (it->second == url) { return it->first; } } Rf_error("Couldn't find prefix for url %s", url.c_str()); return std::string(); } bool add(const xmlChar* prefix, const xmlChar* url) { return add(Xml2String(prefix).asStdString(), Xml2String(url).asStdString()); } bool add(std::string prefix, std::string url) { prefix2url.insert(prefix2url_t::value_type(prefix, url)); return true; } SEXP out() { SEXP out = PROTECT(Rf_allocVector(STRSXP, prefix2url.size())); SEXP names = PROTECT(Rf_allocVector(STRSXP, prefix2url.size())); size_t i = 0; for (prefix2url_t::const_iterator it = prefix2url.begin(); it != prefix2url.end(); ++it) { SET_STRING_ELT(out, i, Rf_mkChar(it->second.c_str())); SET_STRING_ELT(names, i, Rf_mkChar(it->first.c_str())); ++i; } Rf_setAttrib(out, R_NamesSymbol, names); UNPROTECT(2); return out; } }; #endif xml2/src/connection.cpp0000644000176200001440000000247313640647412014603 0ustar liggesusers#include #include #include "xml2_utils.h" // Wrapper around R's read_bin function SEXP read_bin(SEXP con, size_t bytes) { SEXP e; SEXP raw_sxp = PROTECT(Rf_mkString("raw")); SEXP bytes_sxp = PROTECT(Rf_ScalarInteger(bytes)); PROTECT(e = Rf_lang4(Rf_install("readBin"), con, raw_sxp, bytes_sxp)); SEXP res = Rf_eval(e, R_GlobalEnv); UNPROTECT(3); return res; } // Wrapper around R's write_bin function SEXP write_bin(SEXP data, SEXP con) { SEXP e; PROTECT(e = Rf_lang3(Rf_install("writeBin"), data, con)); SEXP res = Rf_eval(e, R_GlobalEnv); UNPROTECT(1); return res; } // Read data from a connection in chunks and then combine into a single // raw vector. // // [[export]] extern "C" SEXP read_connection_(SEXP con_sxp, SEXP read_size_sxp) { BEGIN_CPP std::vector buffer; size_t read_size = REAL(read_size_sxp)[0]; SEXP chunk = read_bin(con_sxp, read_size); R_xlen_t chunk_size = Rf_xlength(chunk); while(chunk_size > 0) { std::copy(RAW(chunk), RAW(chunk) + chunk_size, std::back_inserter(buffer)); chunk = read_bin(con_sxp, read_size); chunk_size = Rf_xlength(chunk); } size_t size = buffer.size(); SEXP out = PROTECT(Rf_allocVector(RAWSXP, size)); std::copy(buffer.begin(), buffer.end(), RAW(out)); UNPROTECT(1); return out; END_CPP } xml2/src/Makevars.win0000644000176200001440000000056013631515545014224 0ustar liggesusersVERSION=2.9.8 RWINLIB=../windows/libxml2-$(VERSION) PKG_CPPFLAGS=-I../inst/include -I$(RWINLIB)/include/libxml2 \ -DLIBXML_STATIC PKG_LIBS=-L$(RWINLIB)/lib${R_ARCH} -lxml2 -llzma -liconv -lz -lws2_32 all: clean winlibs clean: rm -f $(OBJECTS) $(SHLIB) winlibs: "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R" $(VERSION) .PHONY: all winlibs clean xml2/src/xml2_namespace.cpp0000644000176200001440000000351713640650307015337 0ustar liggesusers#include #include #include "xml2_types.h" #include "xml2_utils.h" // [[export]] extern "C" SEXP unique_ns(SEXP ns) { BEGIN_CPP return NsMap(ns).out(); END_CPP } void cache_namespace(xmlNode* node, NsMap* nsMap) { // Iterate over namespace definitions for(xmlNs* cur = node->nsDef; cur != NULL; cur = cur->next) { nsMap->add(cur->prefix, cur->href); } // Iterate over children, calling this function recursively //for(xmlNode* cur = node->children; cur != NULL; cur = cur->next) for(xmlNode* cur = node->children; cur != NULL && cur->type != XML_ENTITY_DECL; cur = cur->next) cache_namespace(cur, nsMap); } // [[export]] extern "C" SEXP doc_namespaces(SEXP doc_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); NsMap nsMap; xmlNode* root = xmlDocGetRootElement(doc.checked_get()); cache_namespace(root, &nsMap); return nsMap.out(); END_CPP } // [[export]] extern "C" SEXP ns_lookup_uri(SEXP doc_sxp, SEXP node_sxp, SEXP uri_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); XPtrNode node(node_sxp); xmlNsPtr ns = xmlSearchNsByHref(doc.checked_get(), node.checked_get(), asXmlChar(uri_sxp)); if (ns == NULL) { Rf_error("No namespace with URI `%s` found", CHAR(STRING_ELT(uri_sxp, 0))); } XPtrNs out(ns); return SEXP(out); END_CPP } // [[export]] extern "C" SEXP ns_lookup(SEXP doc_sxp, SEXP node_sxp, SEXP prefix_sxp) { BEGIN_CPP XPtrDoc doc(doc_sxp); XPtrNode node(node_sxp); xmlNsPtr ns = NULL; if (Rf_xlength(STRING_ELT(prefix_sxp, 0)) == 0) { ns = xmlSearchNs(doc.checked_get(), node.checked_get(), NULL); } else { ns = xmlSearchNs(doc.checked_get(), node.checked_get(), asXmlChar(prefix_sxp)); if (ns == NULL) { Rf_error("No namespace with prefix `%s` found", CHAR(STRING_ELT(prefix_sxp, 0))); } } XPtrNs out(ns); return SEXP(out); END_CPP } xml2/src/xml2_schema.cpp0000644000176200001440000000263013640647425014645 0ustar liggesusers#include #include #include "xml2_types.h" #include #include #include "xml2_utils.h" void handleSchemaError(void* userData, xmlError* error) { std::vector * vec = (std::vector *) userData; std::string message = std::string(error->message); message.resize(message.size() - 1); vec->push_back(message); } // [[export]] extern "C" SEXP doc_validate(SEXP doc_sxp, SEXP schema_sxp) { XPtrDoc doc(doc_sxp); XPtrDoc schema(schema_sxp); xmlLineNumbersDefault(1); BEGIN_CPP std::vector vec; xmlSchemaParserCtxtPtr cptr = xmlSchemaNewDocParserCtxt(schema.checked_get()); xmlSchemaSetParserStructuredErrors(cptr, handleSchemaError, &vec); xmlSchemaPtr sptr = xmlSchemaParse(cptr); xmlSchemaValidCtxtPtr vptr = xmlSchemaNewValidCtxt(sptr); xmlSchemaSetValidStructuredErrors(vptr, handleSchemaError, &vec); SEXP out = PROTECT(Rf_allocVector(LGLSXP, 1)); LOGICAL(out)[0] = xmlSchemaValidateDoc(vptr, doc.checked_get()) == 0; xmlSchemaFreeParserCtxt(cptr); xmlSchemaFreeValidCtxt(vptr); xmlSchemaFree(sptr); SEXP errors = PROTECT(Rf_allocVector(STRSXP, vec.size())); for (size_t i = 0; i < vec.size(); ++i) { SET_STRING_ELT(errors, i, Rf_mkCharLenCE(vec[i].c_str(), vec[i].size(), CE_UTF8)); } Rf_setAttrib(out, Rf_install("errors"), errors); UNPROTECT(2); return out; END_CPP } xml2/src/Makevars.in0000644000176200001440000000015213637646422014037 0ustar liggesusersPKG_CPPFLAGS=-I../inst/include @cflags@ -DUCHAR_TYPE=wchar_t PKG_CXXFLAGS=$(C_VISIBILITY) PKG_LIBS=@libs@ xml2/vignettes/0000755000176200001440000000000013643426274013157 5ustar liggesusersxml2/vignettes/modification.Rmd0000644000176200001440000001175613631515545016277 0ustar liggesusers--- title: "Node Modification" author: "Jim Hester" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Node Modification} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, echo = FALSE, message = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(xml2) library(magrittr) ``` # Modifying Existing XML Modifying existing XML can be done in xml2 by using the replacement functions of the accessors. They all have methods for both individual `xml_node` objects as well as `xml_nodeset` objects. If a vector of values is provided it is applied piecewise over the nodeset, otherwise the value is recycled. ## Text Modification ## Text modification only happens on text nodes. If a given node has more than one text node only the first will be affected. If you want to modify additional text nodes you need to select them explicitly with `/text()`. ```{r} x <- read_xml("

This is some text. This is more.

") xml_text(x) xml_text(x) <- "This is some other text." xml_text(x) # You can avoid this by explicitly selecting the text node. x <- read_xml("

This is some text. This is bold!

") text_only <- xml_find_all(x, "//text()") xml_text(text_only) <- c("This is some other text. ", "Still bold!") xml_text(x) xml_structure(x) ``` ## Attribute and Namespace Definition Modification ## Attributes and namespace definitions are modified one at a time with `xml_attr()` or all at once with `xml_attrs()`. In both cases using `NULL` as the value will remove the attribute completely. ```{r} x <- read_xml("
xml2") xml_attr(x, "href") xml_attr(x, "href") <- "https://github.com/r-lib/xml2" xml_attr(x, "href") xml_attrs(x) <- c(id = "xml2", href = "https://github.com/r-lib/xml2") xml_attrs(x) x xml_attrs(x) <- NULL x # Namespaces are added with as a xmlns or xmlns:prefix attribute xml_attr(x, "xmlns") <- "http://foo" x xml_attr(x, "xmlns:bar") <- "http://bar" x ``` ## Name Modification ## Node names are modified with `xml_name()`. ```{r} x <- read_xml("") x xml_name(x) xml_name(x) <- "c" x ``` # Node modification # All of these functions have a `.copy` argument. If this is set to `FALSE` they will remove the new node from its location before inserting it into the new location. Otherwise they make a copy of the node before insertion. ## Replacing existing nodes ## ```{r} x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_replace(t1, t3) x ``` ## Add a sibling ## ```{r} x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_add_sibling(t1, t3) x xml_add_sibling(t3, t1, where = "before") x ``` ## Add a child ## ```{r} x <- read_xml("123") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_add_child(t1, t3) x xml_add_child(t1, read_xml("")) x ``` ## Removing nodes ## The `xml_remove()` can be used to remove a node (and its children) from a tree. The default behavior is to unlink the node from the tree, but does _not_ free the memory for the node, so R objects pointing to the node are still valid. This allows code like the following to work without crashing R ```{r} x <- read_xml("") x1 <- x %>% xml_children() %>% .[[1]] x2 <- x1 %>% xml_children() %>% .[[1]] xml_remove(x1) rm(x1) gc() x2 ``` If you are not planning on referencing these nodes again this memory is wasted. Calling `xml_remove(free = TRUE)` will remove the nodes _and_ free the memory used to store them. **Note** In this case _any_ node which previously pointed to the node or its children will instead be pointing to free memory and may cause R to crash. xml2 can't figure this out for you, so it's your responsibility to remove any objects which are no longer valid. In particular `xml_find_*()` results are easy to overlook, for example ```{r} x <- read_xml("") bees <- xml_find_all(x, "//b") xml_remove(xml_child(x), free = TRUE) # bees[[1]] is no longer valid!!! rm(bees) gc() ``` ## Namespaces ## We want to construct a document with the following namespace layout. (From http://stackoverflow.com/questions/32939229/creating-xml-in-r-with-namespaces/32941524#32941524). ```xml My Layer ``` ```{r} d <- xml_new_root("sld", xmlns = "http://www.o.net/sld", "xmlns:ogc" = "http://www.o.net/ogc", "xmlns:se" = "http://www.o.net/se", version = "1.1.0") %>% xml_add_child("layer") %>% xml_add_child("se:Name", "My Layer") %>% xml_root() d ``` xml2/vignettes/releases/0000755000176200001440000000000013640705667014765 5ustar liggesusersxml2/vignettes/releases/xml2-1.1.1.Rmd0000644000176200001440000000570613640705667016757 0ustar liggesusers--- title: xml2 1.1.1 output: html_fragment --- ```{r setup, include=FALSE} library(xml2) library(xslt) library(magrittr) knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` Today we are pleased to release version 1.1.1 of xml2. xml2 makes it easy to read, create, and modify XML with R. You can install it with: ```{r, eval = FALSE} install.packages("xml2") ``` As well as fixing many bugs, this release: * Makes it easier to create an modify XML * Improves roundtrip support between XML and lists * Adds support for XML validation and XSLT transformations. You can see a full list of changes in the [release notes](https://github.com/r-lib/xml2/releases/tag/v1.1.1). This is the first release maintained by [Jim Hester](https://github.com/jimhester). ## Creating and modifying XML xml2 has been overhauled with a set of methods to make generating and modfying XML easier: * `xml_new_root()` can be used to create a new document and root node simultaneously. ```{r} xml_new_root("x") %>% xml_add_child("y") %>% xml_root() ``` * New `xml_set_text()`, `xml_set_name()`, `xml_set_attr()`, and `xml_set_attrs()` make it easy to modify nodes within a pipeline. ```{r} x <- read_xml(" ") x x %>% xml_find_all(".//b") %>% xml_set_name("banana") %>% xml_set_attr("oldname", "b") x ``` * New `xml_add_parent()` makes it easy to insert a node as the parent of an existing node. * You can create more esoteric node types with `xml_comment()` (comments), `xml_cdata()` (CDATA nodes), and `xml_dtd()` (DTDs). ## Coercion to and from R Lists xml2 1.1.1 improves support for converting to and from R lists, thanks in part to work by [Peter Foley](https://github.com/peterfoley) and [Jenny Bryan](https://github.com/jennybc). In particular xml2 now supports preserving the root node name as well as saving all xml2 attributes as R attributes. These changes allows you to convert most XML documents to and from R lists with `as_list()` and `as_xml_document()` without loss of data. ```{r} x <- read_xml("") x as_list(x) as_xml_document(as_list(x)) ``` ## XML validation and xslt xml2 1.1.1 also adds support for XML validation, thanks to [Jeroen Ooms](https://github.com/jeroenooms). Simply read the document and schema files and call `xml_validate()`. ```{r} doc <- read_xml(system.file("extdata/order-doc.xml", package = "xml2")) schema <- read_xml(system.file("extdata/order-schema.xml", package = "xml2")) xml_validate(doc, schema) ``` Jeroen also released the first xml2 extension package in conjunction with xml2 1.1.1, [xslt](https://cran.r-project.org/package=xslt). xslt allows one to apply [XSLT (Extensible Stylesheet Language Transformations)](https://en.wikipedia.org/wiki/XSLT) to XML documents, which are great for transforming XML data into other formats such as HTML. xml2/configure.win0000644000176200001440000000000013516067254013633 0ustar liggesusersxml2/R/0000755000176200001440000000000013643426275011351 5ustar liggesusersxml2/R/classes.R0000644000176200001440000001530413637645657013146 0ustar liggesusers#' @useDynLib xml2, .registration = TRUE NULL # node ------------------------------------------------------------------------- xml_node <- function(node = NULL, doc = NULL) { if (inherits(node, "xml_node")) { node } else { structure(list(node = node, doc = doc), class = "xml_node") } } #' @export as.character.xml_node <- function(x, ..., options = "format", encoding = "UTF-8") { options <- parse_options(options, xml_save_options()) .Call(node_write_character, x$node, encoding, options) } #' @export print.xml_node <- function(x, width = getOption("width"), max_n = 20, ...) { cat("{", doc_type(x), "_node}\n", sep = "") cat(format(x), "\n", sep = "") show_nodes(xml_children(x), width = width, max_n = max_n) } #' @export print.xml_missing <- function(x, width = getOption("width"), max_n = 20, ...) { cat("{xml_missing}\n") cat(format(x), "\n", sep = "") } # document --------------------------------------------------------------------- xml_document <- function(doc) { if (.Call(doc_has_root, doc)) { x <- xml_node(.Call(doc_root, doc), doc) class(x) <- c("xml_document", class(x)) x } else { structure(list(doc = doc), class = "xml_document") } } doc_type <- function(x) { if (is.null(x$doc)) { return("xml") } if (.Call(doc_is_html, x$doc)) { "html" } else { "xml" } } #' @export print.xml_document <- function(x, width = getOption("width"), max_n = 20, ...) { doc <- xml_document(x$doc) cat("{", doc_type(x), "_document}\n", sep = "") if (inherits(doc, "xml_node")) { cat(format(doc), "\n", sep = "") show_nodes(xml_children(doc), width = width, max_n = max_n) } } #' @export as.character.xml_document <- function(x, ..., options = "format", encoding = "UTF-8") { options <- parse_options(options, xml_save_options()) .Call(doc_write_character, x$doc, encoding, options) } # nodeset ---------------------------------------------------------------------- xml_nodeset <- function(nodes = list(), deduplicate = TRUE) { if (isTRUE(deduplicate)) { nodes <- nodes[!.Call(nodes_duplicated, nodes)] } structure(nodes, class = "xml_nodeset") } #' @param nodes A list (possible nested) of external pointers to nodes #' @return a nodeset #' @noRd make_nodeset <- function(nodes, doc) { nodes <- unlist(nodes, recursive = FALSE) xml_nodeset(lapply(nodes, xml_node, doc = doc)) } #' @export print.xml_nodeset <- function(x, width = getOption("width"), max_n = 20, ...) { n <- length(x) cat("{", doc_type(x), "_nodeset (", n, ")}\n", sep = "") if (n > 0) show_nodes(x, width = width, max_n = max_n) } #' @export as.character.xml_nodeset <- function(x, ...) { vapply(x, as.character, FUN.VALUE = character(1)) } #' @export `[.xml_nodeset` <- function(x, i, ...) { if (length(x) == 0) { return(x) } xml_nodeset(NextMethod()) } show_nodes <- function(x, width = getOption("width"), max_n = 20) { stopifnot(inherits(x, "xml_nodeset")) n <- length(x) if (n == 0) return() if (n > max_n) { n <- max_n x <- x[seq_len(n)] trunc <- TRUE } else { trunc <- FALSE } label <- format(paste0("[", seq_len(n), "]"), justify = "right") contents <- encodeString(vapply(x, as.character, FUN.VALUE = character(1))) desc <- paste0(label, " ", contents) needs_trunc <- nchar(desc) > width desc[needs_trunc] <- paste(substr(desc[needs_trunc], 1, width - 3), "...") cat(desc, sep = "\n") if (trunc) { cat("...\n") } invisible() } nodeset_apply <- function(x, fun, ...) UseMethod("nodeset_apply") #' @export nodeset_apply.xml_missing <- function(x, fun, ...) { xml_nodeset() } #' @export nodeset_apply.xml_nodeset <- function(x, fun, ...) { if (length(x) == 0) return(xml_nodeset()) is_missing <- is.na(x) res <- list(length(x)) res[is_missing] <- list(xml_missing()) if (any(!is_missing)) { res[!is_missing] <- lapply(x[!is_missing], function(x) fun(x$node, ...)) } make_nodeset(res, x[[1]]$doc) } #' @export nodeset_apply.xml_node <- function(x, fun, ...) { nodes <- fun(x$node, ...) xml_nodeset(lapply(nodes, xml_node, doc = x$doc)) } #' @export nodeset_apply.xml_document <- function(x, fun, ...) { if (inherits(x, "xml_node")) { NextMethod() } else { xml_nodeset() } } #' @export format.xml_node <- function(x, ...) { attrs <- xml_attrs(x) paste("<", paste( c(xml_name(x), format_attributes(attrs)), collapse = " "), ">", sep = "") } format_attributes <- function(x) { if (length(x) == 0) { character(0) } else { paste(names(x), quote_str(x), sep = "=") } } #' Construct an missing xml object #' @export #' @keywords internal xml_missing <- function() { structure(list(), class = "xml_missing") } #' @export is.na.xml_missing <- function(x) { TRUE } #' @export is.na.xml_nodeset <- function(x) { vapply(x, is.na, logical(1)) } #' @export is.na.xml_node <- function(x) { FALSE } format.xml_missing <- function(x, ...) { "" } #' @export as.character.xml_missing <- function(x, ...) { NA_character_ } # These mimic the behavior of NA[[1]], NA[[2]], NA[1], NA[2] #' @export `[.xml_missing` <- function(x, i, ...) x #' @export `[[.xml_missing` <- function(x, i, ...) if (i == 1L) x else stop("subscript out of bounds") #' Construct a cdata node #' @param content The CDATA content, does not include `")) #' as.character(x) #' @export xml_cdata <- function(content) { structure(content, class = "xml_cdata") } #' Construct a comment node #' @param content The comment content #' @examples #' x <- xml_new_document() #' r <- xml_add_child(x, "root") #' xml_add_child(r, xml_comment("Hello!")) #' as.character(x) #' @export xml_comment <- function(content) { structure(content, class = "xml_comment") } #' Construct a document type definition #' #' This is used to create simple document type definitions. If you need to #' create a more complicated definition with internal subsets it is recommended #' to parse a string directly with `read_xml()`. #' @param name The name of the declaration #' @param external_id The external ID of the declaration #' @param system_id The system ID of the declaration #' @examples #' r <- xml_new_root( #' xml_dtd("html", #' "-//W3C//DTD XHTML 1.0 Transitional//EN", #' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")) #' #' # Use read_xml directly for more complicated DTD #' d <- read_xml( #' ' #' #' ]> #' This is a valid document &foo; !') #' @export xml_dtd <- function(name = "", external_id = "", system_id = "") { structure(list(name = name, external_id = external_id, system_id = system_id), class = "xml_dtd") } xml2/R/xml_url.R0000644000176200001440000000453313637645657013175 0ustar liggesusers#' The URL of an XML document #' #' This is useful for interpreting relative urls with [url_relative()]. #' #' @param x A node or document. #' @return A character vector of length 1. Returns `NA` if the name is #' not set. #' @export #' @examples #' catalog <- read_xml(xml2_example("cd_catalog.xml")) #' xml_url(catalog) #' #' x <- read_xml("") #' xml_url(x) xml_url <- function(x) { UseMethod("xml_url") } #' @export xml_url.xml_missing <- function(x) { NA_character_ } #' @export xml_url.xml_node <- function(x) { .Call(doc_url, x$doc) } #' @export xml_url.xml_nodeset <- function(x) { vapply(x, function(x) .Call(doc_url, x), character(1)) } #' Convert between relative and absolute urls. #' #' @param x A character vector of urls relative to that base #' @param base A string giving a base url. #' @return A character vector of urls #' @seealso \code{\link{xml_url}} to retrieve the URL associated with a document #' @export #' @examples #' url_absolute(c(".", "..", "/", "/x"), "http://hadley.nz/a/b/c/d") #' #' url_relative("http://hadley.nz/a/c", "http://hadley.nz") #' url_relative("http://hadley.nz/a/c", "http://hadley.nz/") #' url_relative("http://hadley.nz/a/c", "http://hadley.nz/a/b") #' url_relative("http://hadley.nz/a/c", "http://hadley.nz/a/b/") #' @export url_absolute <- function(x, base) { .Call(url_absolute_, x, base) } #' @rdname url_absolute #' @export url_relative <- function(x, base) { .Call(url_relative_, x, base) } #' Escape and unescape urls. #' #' @param x A character vector of urls. #' @param reserved A string containing additional characters to avoid escaping. #' @export #' @examples #' url_escape("a b c") #' url_escape("a b c", "") #' #' url_unescape("a%20b%2fc") #' url_unescape("%C2%B5") url_escape <- function(x, reserved = "") { .Call(url_escape_, x, reserved) } #' @rdname url_escape #' @export url_unescape <- function(x) { .Call(url_unescape_, x) } #' Parse a url into its component pieces. #' #' @param x A character vector of urls. #' @return A dataframe with one row for each element of \code{x} and #' columns: scheme, server, port, user, path, query, fragment. #' @export #' @examples #' url_parse("http://had.co.nz/") #' url_parse("http://had.co.nz:1234/") #' url_parse("http://had.co.nz:1234/?a=1&b=2") #' url_parse("http://had.co.nz:1234/?a=1&b=2#def") url_parse <- function(x) { .Call(url_parse_, x) } xml2/R/xml_serialize.R0000644000176200001440000000417713631515545014350 0ustar liggesusers#' Serializing XML objects to connections. #' #' @inheritParams base::serialize #' @param ... Additional arguments passed to [read_xml()]. #' @inherit base::serialize return #' @examples #' library(xml2) #' x <- read_xml(" #' 123 #' 456 #' ") #' #' b <- xml_find_all(x, "//b") #' out <- xml_serialize(b, NULL) #' xml_unserialize(out) #' @export xml_serialize <- function(object, connection, ...) UseMethod("xml_serialize") #' @export xml_serialize.xml_document <- function(object, connection, ...) { if (is.character(connection)) { connection <- file(connection, "w", raw = TRUE) on.exit(close(connection)) } serialize(structure(as.character(object, ...), class = "xml_serialized_document"), connection) } #' @export xml_serialize.xml_node <- function(object, connection, ...) { if (is.character(connection)) { connection <- file(connection, "w", raw = TRUE) on.exit(close(connection)) } x <- as_xml_document(object) serialize(structure(as.character(x, ...), class = "xml_serialized_node"), connection) } #' @export xml_serialize.xml_nodeset <- function(object, connection, ...) { if (is.character(connection)) { connection <- file(connection, "w", raw = TRUE) on.exit(close(connection)) } x <- as_xml_document(object, "root") serialize(structure(as.character(x, ...), class = "xml_serialized_nodeset"), connection) } #' @rdname xml_serialize #' @export xml_unserialize <- function(connection, ...) { if (is.character(connection)) { connection <- file(connection, "r", raw = TRUE) on.exit(close(connection)) } object <- unserialize(connection) if (inherits(object, "xml_serialized_nodeset")) { x <- read_xml(unclass(object), ...) # Select only the direct children of the root res <- xml_find_all(x, "/*/node()") } else if (inherits(object, "xml_serialized_node")) { x <- read_xml(unclass(object), ...) # Select only the root res <- xml_find_first(x, "/node()") } else if (inherits(object, "xml_serialized_document")) { res <- read_xml(unclass(object), ...) } else { stop("Not a serialized xml2 object", call. = FALSE) } res } xml2/R/xml_modify.R0000644000176200001440000002400613637645657013657 0ustar liggesusers#' Modify a tree by inserting, replacing or removing nodes #' #' `xml_add_sibling()` and `xml_add_child()` are used to insert a node #' as a sibling or a child. `xml_add_parent()` adds a new parent in #' between the input node and the current parent. `xml_replace()` #' replaces an existing node with a new node. `xml_remove()` removes a #' node from the tree. #' #' @details Care needs to be taken when using `xml_remove()`, #' @param .x a document, node or nodeset. #' @param .copy whether to copy the `.value` before replacing. If this is `FALSE` #' then the node will be moved from it's current location. #' @param .where to add the new node, for `xml_add_child` the position #' after which to add, use `0` for the first child. For #' `xml_add_sibling` either \sQuote{"before"} or \sQuote{"after"} #' indicating if the new node should be before or after `.x`. #' @param ... If named attributes or namespaces to set on the node, if unnamed #' text to assign to the node. #' @param .value node to insert. #' @param free When removing the node also free the memory used for that node. #' Note if you use this option you cannot use any existing objects pointing to #' the node or its children, it is likely to crash R or return garbage. #' @export xml_replace <- function(.x, .value, ..., .copy = TRUE) { UseMethod("xml_replace") } #' @export xml_replace.xml_node <- function(.x, .value, ..., .copy = TRUE) { node <- create_node(.value, .parent = .x, .copy = .copy, ...) .x$node <- .Call(node_replace, .x$node, node$node) node } #' @export xml_replace.xml_nodeset <- function(.x, .value, ..., .copy = TRUE) { if (length(.x) == 0) { return(.x) } # Need to wrap this in a list if a bare xml_node so it is recycled properly if (inherits(.value, "xml_node")) { .value <- list(.value) } Map(xml_replace, .x, .value, ..., .copy = .copy) } #' @export xml_replace.xml_missing <- function(.x, .value, ..., .copy = TRUE) { .x } #' @rdname xml_replace #' @export xml_add_sibling <- function(.x, .value, ..., .where = c("after", "before"), .copy = TRUE) { UseMethod("xml_add_sibling") } #' @export xml_add_sibling.xml_node <- function(.x, .value, ..., .where = c("after", "before"), .copy = inherits(.value, "xml_node")) { .where <- match.arg(.where) node <- create_node(.value, .parent = .x, .copy = .copy, ...) .x$node <- switch(.where, before = .Call(node_prepend_sibling, .x$node, node$node), after = .Call(node_append_sibling, .x$node, node$node)) invisible(.x) } #' @export xml_add_sibling.xml_nodeset <- function(.x, .value, ..., .where = c("after", "before"), .copy = TRUE) { if (length(.x) == 0) { return(.x) } .where <- match.arg(.where) # Need to wrap this in a list if a bare xml_node so it is recycled properly if (inherits(.value, "xml_node")) { .value <- list(.value) } invisible(Map(xml_add_sibling, rev(.x), rev(.value), ..., .where = .where, .copy = .copy)) } #' @export xml_add_sibling.xml_missing <- function(.x, .value, ..., .where = c("after", "before"), .copy = TRUE) { .x } # Helper function used in the xml_add* methods create_node <- function(.value, ..., .parent, .copy) { if (inherits(.value, "xml_node")) { if (isTRUE(.copy)) { .value$node <- .Call(node_copy, .value$node) } return(.value) } if (inherits(.value, "xml_cdata")) { return(xml_node(.Call(node_cdata_new, .parent$doc, .value), doc = .parent$doc)) } if (inherits(.value, "xml_comment")) { return(xml_node(.Call(node_comment_new, .value), doc = .parent$doc)) } if (inherits(.value, "xml_dtd")) { .Call(node_new_dtd, .parent$doc, .value$name, .value$external_id, .value$system_id) return() } if (!is.character(.value)) { stop("`.value` must be a character", call. = FALSE) } parts <- strsplit(.value, ":")[[1]] if (length(parts) == 2 && !is.null(.parent$node)) { namespace <- .Call(ns_lookup, .parent$doc, .parent$node, parts[[1]]) node <- structure(list(node = .Call(node_new_ns, parts[[2]], namespace), doc = .parent$doc), class = "xml_node") } else { node <- structure(list(node = .Call(node_new, .value), doc = .parent$doc), class = "xml_node") } args <- list(...) named <- has_names(args) xml_attrs(node) <- args[named] xml_text(node) <- paste(args[!named], collapse = "") node } #' @rdname xml_replace #' @export xml_add_child <- function(.x, .value, ..., .where = length(xml_children(.x)), .copy = TRUE) { UseMethod("xml_add_child") } #' @export xml_add_child.xml_node <- function(.x, .value, ..., .where = length(xml_children(.x)), .copy = inherits(.value, "xml_node")) { node <- create_node(.value, .parent = .x, .copy = .copy, ...) if (.where == 0L) { if(.Call(node_has_children, .x$node, TRUE)) { .Call(node_prepend_child, .x$node, node$node) } else { .Call(node_append_child, .x$node, node$node) } } else { num_children <- length(xml_children(.x)) if (.where >= num_children) { .Call(node_append_child, .x$node, node$node) } else .Call(node_append_sibling, xml_child(.x, search = .where)$node, node$node) } invisible(node) } #' @export xml_add_child.xml_document <- function(.x, .value, ..., .where = length(xml_children(.x)), .copy = inherits(.value, "xml_node")) { if (inherits(.x, "xml_node")) { NextMethod("xml_add_child") } else { node <- create_node(.value, .parent = .x, .copy = .copy, ...) if (!is.null(node)) { if (!.Call(doc_has_root, .x$doc)) { .Call(doc_set_root, .x$doc, node$node) } .Call(node_append_child, .Call(doc_root, .x$doc), node$node) } invisible(xml_document(.x$doc)) } } #' @export xml_add_child.xml_nodeset <- function(.x, .value, ..., .where = length(xml_children(.x)), .copy = TRUE) { if (length(.x) == 0) { return(.x) } # Need to wrap this in a list if a bare xml_node so it is recycled properly if (inherits(.value, "xml_node")) { .value <- list(.value) } res <- Map(xml_add_child, .x, .value, ..., .where = .where, .copy = .copy) invisible(make_nodeset(res, res[[1]]$doc)) } #' @export xml_add_child.xml_missing <- function(.x, .value, ..., .copy = TRUE) { .x } #' @rdname xml_replace #' @export xml_add_parent <- function(.x, .value, ...) { UseMethod("xml_add_parent") } #' @export xml_add_parent.xml_node <- function(.x, .value, ...) { new_parent <- xml_replace(.x, .value = .value, ..., .copy = FALSE) node <- xml_add_child(new_parent, .value = .x, .copy = FALSE) invisible(node) } #' @export xml_add_parent.xml_nodeset <- function(.x, .value, ...) { if (length(.x) == 0) { return(.x) } # Need to wrap this in a list if a bare xml_node so it is recycled properly if (inherits(.value, "xml_node")) { .value <- list(.value) } res <- Map(xml_add_parent, .x, .value, ...) invisible(make_nodeset(res, res[[1]]$doc)) } #' @export xml_add_parent.xml_missing <- function(.x, .value, ..., .copy = TRUE) { invisible(.x) } #' @rdname xml_replace #' @export xml_remove <- function(.x, free = FALSE) { UseMethod("xml_remove") } #' @export xml_remove.xml_node <- function(.x, free = FALSE) { .Call(node_remove, .x$node, free) invisible(.x) } #' @export xml_remove.xml_nodeset <- function(.x, free = FALSE) { if (length(.x) == 0) { return(invisible(.x)) } invisible(Map(xml_remove, rev(.x), free = free)) } #' @export xml_remove.xml_missing <- function(.x, free = FALSE) { invisible(.x) } #' Set the node's namespace #' #' The namespace to be set must be already defined in one of the node's #' ancestors. #' @param .x a node #' @param prefix The namespace prefix to use #' @param uri The namespace URI to use #' @return the node (invisibly) #' @export xml_set_namespace <- function(.x, prefix = "", uri = "") { stopifnot(inherits(.x, "xml_node")) if (nzchar(uri)) { .Call(node_set_namespace_uri, .x$doc, .x$node, uri) } else { .Call(node_set_namespace_prefix, .x$doc, .x$node, prefix) } invisible(.x) } #' Create a new document, possibly with a root node #' #' `xml_new_document` creates only a new document without a root node. In #' most cases you should instead use `xml_new_root`, which creates a new #' document and assigns the root node in one step. #' @param version The version number of the document. #' @param encoding The character encoding to use in the document. The default #' encoding is \sQuote{UTF-8}. Available encodings are specified at #' . #' @return A `xml_document` object. #' @export # TODO: jimhester 2016-12-16 Deprecate this in the future? xml_new_document <- function(version = "1.0", encoding = "UTF-8") { doc <- .Call(doc_new, version, encoding) structure(list(doc = doc), class = "xml_document") } #' @param .version The version number of the document, passed to `xml_new_document(version)`. #' @param .encoding The encoding of the document, passed to `xml_new_document(encoding)`. #' @inheritParams xml_add_child #' @rdname xml_new_document #' @export xml_new_root <- function(.value, ..., .copy = inherits(.value, "xml_node"), .version = "1.0", .encoding = "UTF-8") { xml_add_child(xml_new_document(version = .version, encoding = .encoding), .value = .value, ... = ..., .copy = .copy) } #' Strip the default namespaces from a document #' #' @inheritParams xml_name #' @examples #' x <- read_xml( #' " #' #' #' #' #' ") #' # Need to specify the default namespaces to find the baz nodes #' xml_find_all(x, "//d1:baz") #' xml_find_all(x, "//d2:baz") #' #' # After stripping the default namespaces you can find both baz nodes directly #' xml_ns_strip(x) #' xml_find_all(x, "//baz") #' @export xml_ns_strip <- function(x) { # //namespace::*[name()=''] finds all the namespace definition nodes with no # prefix (default namespaces). # What we actually want is the element node the definitions are contained in # so return the parent (/parent::*) namespace_element_nodes <- xml_find_all(x, "//namespace::*[name()='']/parent::*") xml_attr(namespace_element_nodes, "xmlns") <- NULL invisible(x) } xml2/R/xml_path.R0000644000176200001440000000115613637645657013325 0ustar liggesusers#' Retrieve the xpath to a node #' #' This is useful when you want to figure out where nodes matching an #' xpath expression live in a document. #' #' @inheritParams xml_name #' @return A character vector. #' @export #' @examples #' x <- read_xml("") #' xml_path(xml_find_all(x, ".//baz")) xml_path <- function(x) { UseMethod("xml_path") } #' @export xml_path.xml_missing <- function(x) { NA_character_ } #' @export xml_path.xml_node <- function(x) { .Call(node_path, x$node) } #' @export xml_path.xml_nodeset <- function(x) { vapply(x, xml_path, FUN.VALUE = character(1)) } xml2/R/xml_schema.R0000644000176200001440000000127413637645657013632 0ustar liggesusers#' Validate XML schema #' #' Validate an XML document against an XML 1.0 schema. #' #' @inheritParams xml_name #' @return TRUE or FALSE #' @export #' @param schema an XML document containing the schema #' @examples # Example from https://msdn.microsoft.com/en-us/library/ms256129(v=vs.110).aspx #' doc <- read_xml(system.file("extdata/order-doc.xml", package = "xml2")) #' schema <- read_xml(system.file("extdata/order-schema.xml", package = "xml2")) #' xml_validate(doc, schema) xml_validate <- function(x, schema) { UseMethod("xml_validate") } #' @export xml_validate.xml_document <- function(x, schema) { stopifnot(inherits(schema, "xml_document")) .Call(doc_validate, x$doc, schema$doc) } xml2/R/utils.R0000644000176200001440000000425313631515545012634 0ustar liggesusers`%||%` <- function(a, b) if (is.null(a)) b else a is_named <- function(x) { all(has_names(x)) } has_names <- function(x) { nms <- names(x) if (is.null(nms)) { rep(FALSE, length(x)) } else { !(is.na(nms) | nms == "") } } # non smart quote version of sQuote quote_str <- function(x, quote = "\"") { if (!length(x)) { return(character(0)) } paste0(quote, x, quote) } is_installed <- function(pkg) { requireNamespace(pkg, quietly = TRUE) } need_package <- function(pkg) { if (is_installed(pkg)) return(invisible()) stop("Please install ", pkg, " package", call. = FALSE) } # Format the C bitwise flags for display in Rd. The input object is a named # integer vector with a 'descriptions' character vector attribute that # corresponds to each flag. describe_options <- function(x) { paste0("\\describe{\n", paste0(" \\item{", names(x), "}{", attr(x, "descriptions"), "}", collapse = "\n"), "\n}") } s_quote <- function(x) paste0("'", x, "'") # Similar to match.arg, but returns character() with NULL or empty input and # errors if any of the inputs are not found (fixing # https://bugs.r-project.org/bugzilla3/show_bug.cgi?id=16659) parse_options <- function(arg, options) { if (is.numeric(arg)) { return(as.integer(arg)) } if (is.null(arg) || !any(nzchar(arg))) { return(0L) } # set duplicates.ok = TRUE so any duplicates are counted differently than # non-matches, then take only unique results i <- pmatch(arg, names(options), duplicates.ok = TRUE) if (any(is.na(i))) { stop(sprintf("`options` %s is not a valid option, should be one of %s", s_quote(arg[is.na(i)][1L]), paste(s_quote(names(options)), collapse = ", ")), call. = FALSE) } sum(options[unique(i)]) } #' Get path to a xml2 example #' #' xml2 comes bundled with a number of sample files in its \sQuote{inst/extdata} #' directory. This function makes them easy to access. #' @param path Name of file. If `NULL`, the example files will be listed. #' @export xml2_example <- function(path = NULL) { if (is.null(path)) { dir(system.file("extdata", package = "xml2")) } else { system.file("extdata", path, package = "xml2", mustWork = TRUE) } } xml2/R/zzz.R0000644000176200001440000000014713516067254012330 0ustar liggesusers.onUnload <- function(libpath) { gc() # trigger finalisers library.dynam.unload("xml2", libpath) } xml2/R/xml_structure.R0000644000176200001440000000555013631515545014415 0ustar liggesusers#' Show the structure of an html/xml document. #' #' Show the structure of an html/xml document without displaying any of #' the values. This is useful if you want to get a high level view of the #' way a document is organised. Compared to `xml_structure`, #' `html_structure` prints the id and class attributes. #' #' @param x HTML/XML document (or part there of) #' @param indent Number of spaces to ident #' @inheritParams base::cat #' @export #' @examples #' xml_structure(read_xml("")) #' #' rproj <- read_html(system.file("extdata","r-project.html", package = "xml2")) #' xml_structure(rproj) #' xml_structure(xml_find_all(rproj, ".//p")) #' #' h <- read_html("

") #' html_structure(h) xml_structure <- function(x, indent = 2, file = "") { cat(file = file) tree_structure(x, indent = indent, html = FALSE, file = file) } #' @export #' @rdname xml_structure html_structure <- function(x, indent = 2, file = "") { cat(file = file) tree_structure(x, indent = indent, html = TRUE, file = file) } tree_structure <- function(x, indent = 2, html = FALSE, file = "") { UseMethod("tree_structure") } #' @export tree_structure.xml_missing <- function(x, indent = 2, html = FALSE, file = "") { NA_character_ } #' @export tree_structure.xml_nodeset <- function(x, indent = 2, html = FALSE, file = "") { for (i in seq_along(x)) { cat("[[", i, "]]\n", sep = "", file = file, append = TRUE) print_xml_structure(x[[i]], indent = indent, html = html, file = file) cat("\n", file = file, append = TRUE) } invisible() } #' @export tree_structure.xml_node <- function(x, indent = 2, html = FALSE, file = "") { print_xml_structure(x, indent = indent, html = html, file = file) invisible() } print_xml_structure <- function(x, prefix = 0, indent = 2, html = FALSE, file = "") { padding <- paste(rep(" ", prefix), collapse = "") type <- xml_type(x) if (type == "element") { attr <- xml_attrs(x) if (html) { html_attrs <- list() if ("id" %in% names(attr)) { html_attrs$id <- paste0("#", attr[["id"]]) attr <- attr[setdiff(names(attr), "id")] } if ("class" %in% names(attr)) { html_attrs$class <- paste0(".", gsub(" ", ".", attr[["class"]])) attr <- attr[setdiff(names(attr), "class")] } attr_str <- paste(unlist(html_attrs), collapse = " ") } else { attr_str <- "" } if (length(attr) > 0) { attr_str <- paste0(attr_str, " [", paste0(names(attr), collapse = ", "), "]") } node <- paste0("<", xml_name(x), attr_str, ">") cat(padding, node, "\n", sep = "", file = file, append = TRUE) lapply(xml_contents(x), print_xml_structure, prefix = prefix + indent, indent = indent, html = html, file = file) } else { cat(padding, "{", type, "}\n", sep = "", file = file, append = TRUE) } } xml2/R/xml_text.R0000644000176200001440000000607213637645657013357 0ustar liggesusers#' Extract or modify the text #' #' `xml_text` returns a character vector, `xml_double` returns a #' numeric vector, `xml_integer` returns an integer vector. #' @inheritParams xml_name #' @param trim If `TRUE` will trim leading and trailing spaces. #' @return A character vector, the same length as x. #' @examples #' x <- read_xml("

This is some text. This is bold!

") #' xml_text(x) #' xml_text(xml_children(x)) #' #' x <- read_xml("This is some text. This is some nested text.") #' xml_text(x) #' xml_text(xml_find_all(x, "//x")) #' #' x <- read_xml("

Some text

") #' xml_text(x, trim = TRUE) #' #' # xml_double() and xml_integer() are useful for extracting numeric #' attributes #' x <- read_xml("") #' xml_integer(xml_find_all(x, "//@x")) #' @export xml_text <- function(x, trim = FALSE) { UseMethod("xml_text") } #' @export xml_text.xml_missing <- function(x, trim = FALSE) { NA_character_ } #' @export xml_text.xml_node <- function(x, trim = FALSE) { res <- .Call(node_text, x$node) if (isTRUE(trim)) { res <- sub("^[[:space:]\u00a0]+", "", res) res <- sub("[[:space:]\u00a0]+$", "", res) } res } #' @export xml_text.xml_nodeset <- function(x, trim = FALSE) { vapply(x, xml_text, trim = trim, FUN.VALUE = character(1)) } #' @rdname xml_text #' @param value character vector with replacement text. #' @export `xml_text<-` <- function(x, value) { UseMethod("xml_text<-") } #' @export `xml_text<-.xml_nodeset` <- function(x, value) { if (length(x) == 0) { return(x) } # We need to do the modification in reverse order as the modification can # potentially delete nodes Map(`xml_text<-`, rev(x), rev(value)) # what to return here, setting the text could invalidate some nodes in # the nodeset having pointers to free'd memory. x } #' @export `xml_text<-.xml_node` <- function(x, value) { if (xml_type(x) != "text") { text_child <- xml_find_first(x, ".//text()[1]", ns = character()) if (inherits(text_child, "xml_missing")) { .Call(node_append_content, x$node, value) } else { .Call(node_set_content, text_child$node, value) } } else { .Call(node_set_content, x$node, value) } x } #' @export `xml_text<-.xml_missing` <- function(x, value) { NA_character_ } #' @export #' @rdname xml_text `xml_set_text` <- `xml_text<-` #' @rdname xml_text #' @export xml_double <- function(x) { UseMethod("xml_double") } #' @export xml_double.xml_missing <- function(x) { NA_real_ } #' @export xml_double.xml_node <- function(x) { as.numeric(xml_text(x)) } #' @export xml_double.xml_nodeset <- function(x) { vapply(x, xml_double, numeric(1)) } #' @export xml_integer <- function(x) { UseMethod("xml_integer") } #' @export xml_integer.xml_missing <- function(x) { NA_integer_ } #' @rdname xml_text #' @export xml_integer <- function(x) { UseMethod("xml_integer") } #' @export xml_integer.xml_node <- function(x) { as.integer(xml_text(x)) } #' @export xml_integer.xml_nodeset <- function(x) { vapply(x, xml_integer, integer(1)) } xml2/R/paths.R0000644000176200001440000000236013516067254012611 0ustar liggesuserspath_to_connection <- function(path, check = c("file", "dir")) { check <- match.arg(check) if (!is.character(path) || length(path) != 1L) return(path) if (is_url(path)) { if (requireNamespace("curl", quietly = TRUE)) { return(curl::curl(path)) } else { return(url(path)) } } if (check == "file") { path <- check_path(path) } else { path <- file.path(check_path(dirname(path)), basename(path)) } switch(tools::file_ext(path), gz = gzfile(path, ""), bz2 = bzfile(path, ""), xz = xzfile(path, ""), zip = zipfile(path, ""), path ) } is_url <- function(path) { grepl("^(http|ftp)s?://", path) } check_path <- function(path) { if (file.exists(path)) return(normalizePath(path, "/", mustWork = FALSE)) stop("'", path, "' does not exist", if (!is_absolute_path(path)) paste0(" in current working directory ('", getwd(), "')"), ".", call. = FALSE ) } is_absolute_path <- function(path) { grepl("^(/|[A-Za-z]:|\\\\|~)", path) } zipfile <- function(path, open = "r") { files <- utils::unzip(path, list = TRUE) file <- files$Name[[1]] if (nrow(files) > 1) { message("Multiple files in zip: reading '", file, "'") } unz(path, file, open = open) } xml2/R/as_xml_document.R0000644000176200001440000000412313637645657014667 0ustar liggesusers#' Coerce a R list to xml nodes. #' #' This turns an R list into the equivalent XML document. Not all R lists will #' produce valid XML, in particular there can only be one root node and all #' child nodes need to be named (or empty) lists. R attributes become XML #' attributes and R names become XML node names. #' #' @inheritParams as_list #' @include as_list.R xml_parse.R #' @export #' @examples # empty lists generate empty nodes #'as_xml_document(list(x = list())) #' #'# Nesting multiple nodes #'as_xml_document(list(foo = list(bar = list(baz = list())))) #' #'# attributes are stored as R attributes #'as_xml_document(list(foo = structure(list(), id = "a"))) #'as_xml_document(list(foo = list( #' bar = structure(list(), id = "a"), #' bar = structure(list(), id = "b")))) as_xml_document <- function(x, ...) { UseMethod("as_xml_document") } #' @export as_xml_document.character <- read_xml.character #' @export as_xml_document.raw <- read_xml.raw #' @export as_xml_document.connection <- read_xml.connection #' @export as_xml_document.response <- read_xml.response #' @export as_xml_document.list <- function(x, ...) { if (length(x) > 1) { stop("Root nodes must be of length 1", call. = FALSE) } add_node <- function(x, parent, tag = NULL) { if (is.atomic(x)) { return(.Call(node_new_text, parent$node, as.character(x))) } if (!is.null(tag)) { parent <- xml_add_child(parent, tag) attr <- r_attrs_to_xml(attributes(x)) for (i in seq_along(attr)) { xml_set_attr(parent, names(attr)[[i]], attr[[i]]) } } for (i in seq_along(x)) { add_node(x[[i]], parent, names(x)[[i]]) } } doc <- xml_new_document() add_node(x, doc) xml_root(doc) } #' @export as_xml_document.xml_node <- function(x, ...) { xml_new_root(.value = x, ..., .copy = TRUE) } #' @export as_xml_document.xml_nodeset <- function(x, root, ...) { doc <- xml_new_root(.value = root, ..., .copy = TRUE) for (i in seq_along(x)) { xml_add_child(doc, x[[i]], .copy = TRUE) } doc } #' @export as_xml_document.xml_document <- function(x, ...) { x } xml2/R/init.R0000644000176200001440000000041013637645657012444 0ustar liggesusers.onLoad <- function(lib, pkg){ .Call(init_libxml2) } libxml2_version <- function() { as.numeric_version(.Call(libxml2_version_)) } xml_parse_options <- function() { .Call(xml_parse_options_) } xml_save_options <- function() { .Call(xml_save_options_) } xml2/R/xml_name.R0000644000176200001440000000415413637645657013312 0ustar liggesusers#' The (tag) name of an xml element. #' #' @param x A document, node, or node set. #' @param ns Optionally, a named vector giving prefix-url pairs, as produced #' by [xml_ns()]. If provided, all names will be explicitly #' qualified with the ns prefix, i.e. if the element `bar` is defined #' in namespace `foo`, it will be called `foo:bar`. (And #' similarly for attributes). Default namespaces must be given an explicit #' name. The ns is ignored when using [xml_name<-()] and #' [xml_set_name()]. #' @return A character vector. #' @export #' @examples #' x <- read_xml("123") #' xml_name(x) #' #' y <- read_xml("1abc") #' z <- xml_children(y) #' xml_name(xml_children(y)) xml_name <- function(x, ns = character()) { UseMethod("xml_name") } #' @export xml_name.xml_missing <- function(x, ns = character()) { NA_character_ } #' @export xml_name.xml_nodeset <- function(x, ns = character()) { vapply(x, xml_name, ns = ns, FUN.VALUE = character(1)) } #' @export xml_name.xml_node <- function(x, ns = character()) { .Call(node_name, x$node, ns) } #' Modify the (tag) name of an element #' #' @inheritParams xml_name #' @param value a character vector with replacement name. #' @rdname xml_name #' @export `xml_name<-` <- function(x, ns = character(), value) { UseMethod("xml_name<-") } #' @export `xml_name<-.xml_node` <- function(x, ns = character(), value) { .Call(node_set_name, x$node, value) x } #' @export `xml_name<-.xml_nodeset` <- function(x, ns = character(), value) { if (length(x) == 0) { return(x) } if (!is.list(ns)) { ns <- list(ns) } Map(`xml_name<-`, x, ns, value) x } #' @export `xml_name<-.xml_missing` <- function(x, ns = character(), value) { x } set_name <- function(x, value, ns = character()) { xml_name(x = x, ns = ns) <- value x } #' @rdname xml_name #' @inheritParams xml_name #' @export #' @export xml_set_name <- function(x, value, ns = character()) { UseMethod("xml_set_name") } #' @export xml_set_name.xml_node <- set_name #' @export xml_set_name.xml_nodeset <- set_name #' @export xml_set_name.xml_missing <- set_name xml2/R/as_list.R0000644000176200001440000000553513631515545013136 0ustar liggesusers#' Coerce xml nodes to a list. #' #' This turns an XML document (or node or nodeset) into the equivalent R #' list. Note that this is `as_list()`, not `as.list()`: #' `lapply()` automatically calls `as.list()` on its inputs, so #' we can't override the default. #' #' `as_list` currently only handles the four most common types of #' children that an element might have: #' #' \itemize{ #' \item Other elements, converted to lists. #' \item Attributes, stored as R attributes. Attributes that have special meanings in R #' ([class()], [comment()], [dim()], #' [dimnames()], [names()], [row.names()] and #' [tsp()]) are escaped with '.' #' \item Text, stored as a character vector. #' } #' #' @inheritParams xml_name #' @param ... Needed for compatibility with generic. Unused. #' @export #' @examples #' as_list(read_xml(" a ]]>")) #' as_list(read_xml(" ")) #' as_list(read_xml("")) #' as_list(read_xml("")) as_list <- function(x, ns = character(), ...) { UseMethod("as_list") } #' @export as_list.xml_missing <- function(x, ns = character(), ...) { list() } #' @export as_list.xml_document <- function(x, ns = character(), ...) { if (!inherits(x, "xml_node")) { return(list()) } out <- list(NextMethod()) names(out) <- xml_name(x) out } #' @export as_list.xml_node <- function(x, ns = character(), ...) { contents <- xml_contents(x) if (length(contents) == 0) { # Base case - contents type <- xml_type(x) if (type %in% c("text", "cdata")) return(xml_text(x)) if (type != "element" && type != "document") return(paste("[", type, "]")) out <- list() } else { out <- lapply(seq_along(contents), function(i) as_list(contents[[i]], ns = ns)) nms <- ifelse(xml_type(contents) == "element", xml_name(contents, ns = ns), "") if (any(nms != "")) { names(out) <- nms } } # Add xml attributes as R attributes attributes(out) <- c(list(names = names(out)), xml_to_r_attrs(xml_attrs(x, ns = ns))) out } #' @export as_list.xml_nodeset <- function(x, ns = character(), ...) { lapply(seq_along(x), function(i) as_list(x[[i]], ns = ns)) } special_attributes <- c("class", "comment", "dim", "dimnames", "names", "row.names", "tsp") xml_to_r_attrs <- function(x) { if (length(x) == 0) { return(NULL) } # escape special names special <- names(x) %in% special_attributes names(x)[special] <- paste0(".", names(x)[special]) as.list(x) } r_attrs_to_xml <- function(x) { if (length(x) == 0) { return(NULL) } # Drop R special attributes x <- x[!names(x) %in% special_attributes] # Rename any xml attributes needed special <- names(x) %in% paste0(".", special_attributes) names(x)[special] <- sub("^\\.", "", names(x)[special]) x } xml2/R/xml_parse.R0000644000176200001440000001553313637645657013507 0ustar liggesusers#' Read HTML or XML. #' #' @section Setting the "user agent" header: #' #' When performing web scraping tasks it is both good practice --- and often required --- #' to set the [user agent](https://en.wikipedia.org/wiki/User_agent) request header #' to a specific value. Sometimes this value is assigned to emulate a browser in order #' to have content render in a certain way (e.g. `Mozilla/5.0 (Windows NT 5.1; rv:52.0) #' Gecko/20100101 Firefox/52.0` to emulate more recent Windows browsers). Most often, #' this value should be set to provide the web resource owner information on who you are #' and the intent of your actions like this Google scraping bot user agent identifier: #' `Googlebot/2.1 (+http://www.google.com/bot.html)`. #' #' You can set the HTTP user agent for URL-based requests using [httr::set_config()] and [httr::user_agent()]: #' #' `httr::set_config(httr::user_agent("me@@example.com; +https://example.com/info.html"))` #' #' [httr::set_config()] changes the configuration globally, #' [httr::with_config()] can be used to change configuration temporarily. #' #' @param x A string, a connection, or a raw vector. #' #' A string can be either a path, a url or literal xml. Urls will #' be converted into connections either using `base::url` or, if #' installed, `curl::curl`. Local paths ending in `.gz`, #' `.bz2`, `.xz`, `.zip` will be automatically uncompressed. #' #' If a connection, the complete connection is read into a raw vector before #' being parsed. #' @param encoding Specify a default encoding for the document. Unless #' otherwise specified XML documents are assumed to be in UTF-8 or #' UTF-16. If the document is not UTF-8/16, and lacks an explicit #' encoding directive, this allows you to supply a default. #' @param ... Additional arguments passed on to methods. #' @param as_html Optionally parse an xml file as if it's html. #' @param base_url When loading from a connection, raw vector or literal #' html/xml, this allows you to specify a base url for the document. Base #' urls are used to turn relative urls into absolute urls. #' @param n If `file` is a connection, the number of bytes to read per #' iteration. Defaults to 64kb. #' @param verbose When reading from a slow connection, this prints some #' output on every iteration so you know its working. #' @param options Set parsing options for the libxml2 parser. Zero or more of #' \Sexpr[results=rd]{xml2:::describe_options(xml2:::xml_parse_options())} #' @return An XML document. HTML is normalised to valid XML - this may not #' be exactly the same transformation performed by the browser, but it's #' a reasonable approximation. #' @export #' @examples #' # Literal xml/html is useful for small examples #' read_xml("") #' read_html("Hi<title></html>") #' read_html("<html><title>Hi") #' #' # From a local path #' read_html(system.file("extdata", "r-project.html", package = "xml2")) #' #' \dontrun{ #' # From a url #' cd <- read_xml(xml2_example("cd_catalog.xml")) #' me <- read_html("http://had.co.nz") #' } read_xml <- function(x, encoding = "", ..., as_html = FALSE, options = "NOBLANKS") { UseMethod("read_xml") } #' @export #' @rdname read_xml read_html <- function(x, encoding = "", ..., options = c("RECOVER", "NOERROR", "NOBLANKS")) { UseMethod("read_html") } #' @export read_html.default <- function(x, encoding = "", ..., options = c("RECOVER", "NOERROR", "NOBLANKS")) { options <- parse_options(options, xml_parse_options()) suppressWarnings(read_xml(x, encoding = encoding, ..., as_html = TRUE, options = options)) } #' @export read_html.response <- function(x, encoding = "", options = c("RECOVER", "NOERROR", "NOBLANKS"), ...) { need_package("httr") options <- parse_options(options, xml_parse_options()) httr::stop_for_status(x) content <- httr::content(x, as = "raw") xml2::read_html(content, encoding = encoding, options = options, ...) } #' @export #' @rdname read_xml read_xml.character <- function(x, encoding = "", ..., as_html = FALSE, options = "NOBLANKS") { if (length(x) == 0) { stop("Document is empty", call. = FALSE) } options <- parse_options(options, xml_parse_options()) if (grepl("<|>", x)) { read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html, options = options) } else { con <- path_to_connection(x) if (inherits(con, "connection")) { read_xml.connection(con, encoding = encoding, ..., as_html = as_html, base_url = x, options = options) } else { doc <- .Call(doc_parse_file, con, encoding = encoding, as_html = as_html, options = options) xml_document(doc) } } } #' @export #' @rdname read_xml read_xml.raw <- function(x, encoding = "", base_url = "", ..., as_html = FALSE, options = "NOBLANKS") { options <- parse_options(options, xml_parse_options()) doc <- .Call(doc_parse_raw, x, encoding = encoding, base_url = base_url, as_html = as_html, options = options) xml_document(doc) } #' @export #' @rdname read_xml read_xml.connection <- function(x, encoding = "", n = 64 * 1024, verbose = FALSE, ..., base_url = "", as_html = FALSE, options = "NOBLANKS") { options <- parse_options(options, xml_parse_options()) if (!isOpen(x)) { open(x, "rb") on.exit(close(x)) } raw <- .Call(read_connection_, x, n) read_xml.raw(raw, encoding = encoding, base_url = base_url, as_html = as_html, options = options) } #' @export read_xml.response <- function(x, encoding = "", base_url = "", ..., as_html = FALSE, options = "NOBLANKS") { need_package("httr") options <- parse_options(options, xml_parse_options()) httr::stop_for_status(x) content <- httr::content(x, as = "raw") xml2::read_xml(content, encoding = encoding, base_url = if (nzchar(base_url)) base_url else x$url, as_html = as_html, option = options, ...) } #' Download a HTML or XML file #' #' Libcurl implementation of `C_download` (the "internal" download method) #' with added support for https, ftps, gzip, etc. Default behavior is identical #' to [download.file()], but request can be fully configured by passing #' a custom [curl::handle()]. #' @inherit curl::curl_download #' @param file A character string with the name where the downloaded file is #' saved. #' @seealso [curl_download][curl::curl_download] #' @export #' @examples #' \dontrun{ #' download_html("http://tidyverse.org/index.html") #' } download_xml <- function(url, file = basename(url), quiet = TRUE, mode = "wb", handle = curl::new_handle()) { if (!requireNamespace("curl", quietly = TRUE)) { stop("`curl` must be installed to use `download_xml()`", call. = FALSE) } curl::curl_download(url, file, quiet = quiet, mode = mode, handle = handle) invisible(file) } #' @export #' @rdname download_xml download_html <- download_xml ���������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/R/xml_children.R�������������������������������������������������������������������������������0000644�0001762�0000144�00000007011�13637645657�014155� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#' Navigate around the family tree. #' #' `xml_children` returns only elements, `xml_contents` returns #' all nodes. `xml_length` returns the number of children. #' `xml_parent` returns the parent node, `xml_parents` #' returns all parents up to the root. `xml_siblings` returns all nodes #' at the same level. `xml_child` makes it easy to specify a specific #' child to return. #' #' @inheritParams xml_name #' @param only_elements For `xml_length`, should it count all children, #' or just children that are elements (the default)? #' @param search For `xml_child`, either the child number to return (by #' position), or the name of the child node to return. If there are multiple #' child nodes with the same name, the first will be returned #' @return A node or nodeset (possibly empty). Results are always de-duplicated. #' @export #' @examples #' x <- read_xml("<foo> <bar><boo /></bar> <baz/> </foo>") #' xml_children(x) #' xml_children(xml_children(x)) #' xml_siblings(xml_children(x)[[1]]) #' #' # Note the each unique node only appears once in the output #' xml_parent(xml_children(x)) #' #' # Mixed content #' x <- read_xml("<foo> a <b/> c <d>e</d> f</foo>") #' # Childen gets the elements, contents gets all node types #' xml_children(x) #' xml_contents(x) #' #' xml_length(x) #' xml_length(x, only_elements = FALSE) #' #' # xml_child makes it easier to select specific children #' xml_child(x) #' xml_child(x, 2) #' xml_child(x, "baz") xml_children <- function(x) { nodeset_apply(x, function(x) .Call(node_children, x, TRUE)) } #' @export #' @rdname xml_children xml_child <- function(x, search = 1, ns = xml_ns(x)) { if (length(search) != 1) { stop("`search` must be of length 1", call. = FALSE) } if (is.numeric(search)) { xml_children(x)[[search]] } else if (is.character(search)) { xml_find_first(x, xpath = paste0("./", search), ns = ns) } else { stop("`search` must be `numeric` or `character`", call. = FALSE) } } #' @export #' @rdname xml_children xml_contents <- function(x) { nodeset_apply(x, function(x) .Call(node_children, x, FALSE)) } #' @export #' @rdname xml_children xml_parents <- function(x) { nodeset_apply(x, function(x) .Call(node_parents, x)) } #' @export #' @rdname xml_children xml_siblings <- function(x) { nodeset_apply(x, function(x) .Call(node_siblings, x, TRUE)) } #' @export #' @rdname xml_children xml_parent <- function(x) { UseMethod("xml_parent") } #' @export xml_parent.xml_missing <- function(x) { xml_missing() } #' @export xml_parent.xml_node <- function(x) { xml_node(.Call(node_parent, x$node), x$doc) } #' @export xml_parent.xml_nodeset <- function(x) { nodeset_apply(x, function(x) .Call(node_parent, x)) } #' @export #' @rdname xml_children xml_length <- function(x, only_elements = TRUE) { UseMethod("xml_length") } #' @export xml_length.xml_missing <- function(x, only_elements = TRUE) { 0L } #' @export xml_length.xml_node <- function(x, only_elements = TRUE) { .Call(node_length, x$node, only_elements) } #' @export xml_length.xml_nodeset <- function(x, only_elements = TRUE) { if (length(x) == 0) return(0L) vapply(x, xml_length, only_elements = only_elements, FUN.VALUE = integer(1)) } #' @export #' @rdname xml_children xml_root <- function(x) { stopifnot(inherits(x, c("xml_node", "xml_document", "xml_nodeset"))) if (inherits(x, "xml_nodeset")) { if (length(x) == 0) { return(NULL) } else { return(xml_root(x[[1]])) } } if (!.Call(doc_has_root, x$doc)) { xml_missing() } else { xml_document(x$doc) } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/R/xml_type.R�����������������������������������������������������������������������������������0000644�0001762�0000144�00000001577�13637645657�013361� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#' Determine the type of a node. #' #' @inheritParams xml_name #' @export #' @examples #' x <- read_xml("<foo> a <b /> <![CDATA[ blah]]></foo>") #' xml_type(x) #' xml_type(xml_contents(x)) xml_type <- function(x) { UseMethod("xml_type") } #' @export xml_type.xml_missing <- function(x) { NA_character_ } #' @export xml_type.xml_node <- function(x) { xmlElementType[.Call(node_type, x$node)] } #' @export xml_type.xml_nodeset <- function(x) { types <- vapply(x, function(x) .Call(node_type, x$node), integer(1)) xmlElementType[types] } xmlElementType <- c( "element", "attribute", "text", "cdata", "entity_ref", "entity", "pi", "comment", "document", "document_type", "document_frag", "notation", "html_document", "dtd", "element_decl", "attribute_decl", "entity_decl", "namespace_decl", "xinclude_start", "xinclude_end", "docb_document" ) ���������������������������������������������������������������������������������������������������������������������������������xml2/R/xml_write.R����������������������������������������������������������������������������������0000644�0001762�0000144�00000007123�13637645657�013523� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#' Write XML or HTML to disk. #' #' This writes out both XML and normalised HTML. The default behavior will #' output the same format which was read. If you want to force output pass #' `option = "as_xml"` or `option = "as_html"` respectively. #' #' @param x A document or node to write to disk. It's not possible to #' save nodesets containing more than one node. #' @param file Path to file or connection to write to. #' @param encoding The character encoding to use in the document. The default #' encoding is \sQuote{UTF-8}. Available encodings are specified at #' <http://xmlsoft.org/html/libxml-encoding.html#xmlCharEncoding>. #' @param options default: \sQuote{format}. Zero or more of #' \Sexpr[results=rd]{xml2:::describe_options(xml2:::xml_save_options())} #' @param ... additional arguments passed to methods. #' @export #' @examples #' h <- read_html("<p>Hi!</p>") #' #' tmp <- tempfile(fileext = ".xml") #' write_xml(h, tmp, options = "format") #' readLines(tmp) #' #' # write formatted HTML output #' write_html(h, tmp, options = "format") #' readLines(tmp) write_xml <- function(x, file, ...) { UseMethod("write_xml") } #' @export write_xml.xml_missing <- function(x, file, ...) { stop("Missing data cannot be written", call. = FALSE) } #' @rdname write_xml #' @export write_xml.xml_document <- function(x, file, ..., options = "format", encoding = "UTF-8") { options <- parse_options(options, xml_save_options()) file <- path_to_connection(file, check = "dir") if (inherits(file, "connection")) { if (!isOpen(file)) { open(file, "wb") on.exit(close(file)) } .Call(doc_write_connection, x$doc, file, encoding, options) } else { if (!(is.character(file) && length(file) == 1 && nzchar(file))) { stop("`file` must be a non-zero character of length 1", call. = FALSE) } .Call(doc_write_file, x$doc, file, encoding, options) } } #' @export write_xml.xml_nodeset <- function(x, file, ..., options = "format", encoding = "UTF-8") { if (length(x) != 1) { stop("Can only save length 1 node sets", call. = FALSE) } options <- parse_options(options, xml_save_options()) file <- path_to_connection(file, check = "dir") if (inherits(file, "connection")) { if (!isOpen(file)) { open(file, "wb") on.exit(close(file)) } .Call(node_write_connection, x[[1]]$node, file, encoding, options) } else { if (!(is.character(file) && length(file) == 1 && nzchar(file))) { stop("`file` must be a non-zero character of length 1", call. = FALSE) } .Call(node_write_file, x[[1]]$node, file, encoding, options) } } #' @export write_xml.xml_node <- function(x, file, ..., options = "format", encoding = "UTF-8") { options <- parse_options(options, xml_save_options()) file <- path_to_connection(file, check = "dir") if (inherits(file, "connection")) { if (!isOpen(file)) { open(file, "wb") on.exit(close(file)) } .Call(node_write_connection, x$node, file, encoding, options) } else { if (!(is.character(file) && length(file) == 1 && nzchar(file))) { stop("`file` must be a non-zero character of length 1", call. = FALSE) } .Call(node_write_file, x$node, file, encoding, options) } } #' @export #' @rdname write_xml write_html <- function(x, file, ...) { UseMethod("write_html") } #' @export write_html.xml_missing <- function(x, file, ...) { stop("Missing data cannot be written", call. = FALSE) } #' @rdname write_xml #' @export write_html.xml_document <- write_xml.xml_document #' @export write_html.xml_nodeset <- write_xml.xml_nodeset #' @export write_html.xml_node <- write_xml.xml_node ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/R/S4.R�����������������������������������������������������������������������������������������0000644�0001762�0000144�00000001674�13631515545�011766� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#' Register S4 classes #' #' @description #' Classes are exported so they can be re-used within S4 classes, see [methods::setOldClass()]. #' #' `xml_document`: a complete document. #' #' @name xml_document-class #' @family xml_document #' @importFrom methods setOldClass #' @exportClass xml_document #' @rdname oldclass setOldClass("xml_document") #' xml_missing class #' #' `xml_missing`: a missing object, e.g. for an empty result set. #' #' @name xml_missing-class #' @family xml_missing #' @exportClass xml_missing #' @rdname oldclass setOldClass("xml_missing") #' xml_node Class #' #' `xml_node`: a single node in a document. #' #' @name xml_node-class #' @family xml_node #' @exportClass xml_node #' @rdname oldclass setOldClass("xml_node") #' xml_nodeset Class #' #' `xml_nodeset`: a _set_ of nodes within a document. #' #' @name xml_nodeset-class #' @family xml_nodeset #' @exportClass xml_nodeset #' @rdname oldclass setOldClass("xml_nodeset") ��������������������������������������������������������������������xml2/R/xml_find.R�����������������������������������������������������������������������������������0000644�0001762�0000144�00000014263�13637645657�013314� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#' Find nodes that match an xpath expression. #' #' Xpath is like regular expressions for trees - it's worth learning if #' you're trying to extract nodes from arbitrary locations in a document. #' Use `xml_find_all` to find all matches - if there's no match you'll #' get an empty result. Use `xml_find_first` to find a specific match - #' if there's no match you'll get an `xml_missing` node. #' #' @section Deprecated functions: #' `xml_find_one()` has been deprecated. Instead use #' `xml_find_first()`. #' @param xpath A string containing a xpath (1.0) expression. #' @inheritParams xml_name #' @return `xml_find_all` always returns a nodeset: if there are no matches #' the nodeset will be empty. The result will always be unique; repeated #' nodes are automatically de-duplicated. #' #' `xml_find_first` returns a node if applied to a node, and a nodeset #' if applied to a nodeset. The output is *always* the same size as #' the input. If there are no matches, `xml_find_first` will return a #' missing node; if there are multiple matches, it will return the first #' only. #' #' `xml_find_num`, `xml_find_chr`, `xml_find_lgl` return #' numeric, character and logical results respectively. #' @export #' @seealso [xml_ns_strip()] to remove the default namespaces #' @examples #' x <- read_xml("<foo><bar><baz/></bar><baz/></foo>") #' xml_find_all(x, ".//baz") #' xml_path(xml_find_all(x, ".//baz")) #' #' # Note the difference between .// and // #' # // finds anywhere in the document (ignoring the current node) #' # .// finds anywhere beneath the current node #' (bar <- xml_find_all(x, ".//bar")) #' xml_find_all(bar, ".//baz") #' xml_find_all(bar, "//baz") #' #' # Find all vs find one ----------------------------------------------------- #' x <- read_xml("<body> #' <p>Some <b>text</b>.</p> #' <p>Some <b>other</b> <b>text</b>.</p> #' <p>No bold here!</p> #' </body>") #' para <- xml_find_all(x, ".//p") #' #' # If you apply xml_find_all to a nodeset, it finds all matches, #' # de-duplicates them, and returns as a single list. This means you #' # never know how many results you'll get #' xml_find_all(para, ".//b") #' #' # xml_find_first only returns the first match per input node. If there are 0 #' # matches it will return a missing node #' xml_find_first(para, ".//b") #' xml_text(xml_find_first(para, ".//b")) #' #' # Namespaces --------------------------------------------------------------- #' # If the document uses namespaces, you'll need use xml_ns to form #' # a unique mapping between full namespace url and a short prefix #' x <- read_xml(' #' <root xmlns:f = "http://foo.com" xmlns:g = "http://bar.com"> #' <f:doc><g:baz /></f:doc> #' <f:doc><g:baz /></f:doc> #' </root> #' ') #' xml_find_all(x, ".//f:doc") #' xml_find_all(x, ".//f:doc", xml_ns(x)) xml_find_all <- function(x, xpath, ns = xml_ns(x)) { UseMethod("xml_find_all") } #' @export xml_find_all.xml_missing <- function(x, xpath, ns = xml_ns(x)) { xml_nodeset() } #' @export xml_find_all.xml_node <- function(x, xpath, ns = xml_ns(x)) { nodes <- .Call(xpath_search, x$node, x$doc, xpath, ns, Inf) xml_nodeset(nodes) } #' @export xml_find_all.xml_nodeset <- function(x, xpath, ns = xml_ns(x)) { if (length(x) == 0) return(xml_nodeset()) nodes <- unlist(recursive = FALSE, lapply(x, function(x) .Call(xpath_search, x$node, x$doc, xpath, ns, Inf))) xml_nodeset(nodes) } #' @export #' @rdname xml_find_all xml_find_first <- function(x, xpath, ns = xml_ns(x)) { UseMethod("xml_find_first") } xml_find_first.xml_missing <- function(x, xpath, ns = xml_ns(x)) { xml_missing() } #' @export xml_find_first.xml_node <- function(x, xpath, ns = xml_ns(x)) { res <- .Call(xpath_search, x$node, x$doc, xpath, ns, 1) if (length(res) == 1) { res[[1]] } else { res } } #' @export xml_find_first.xml_nodeset <- function(x, xpath, ns = xml_ns(x)) { if (length(x) == 0) return(xml_nodeset()) xml_nodeset(lapply(x, function(x) xml_find_first(x, xpath = xpath, ns = ns)), deduplicate = FALSE) } #' @export #' @rdname xml_find_all xml_find_num <- function(x, xpath, ns = xml_ns(x)) { UseMethod("xml_find_num") } #' @export xml_find_num.xml_node <- function(x, xpath, ns = xml_ns(x)) { res <- .Call(xpath_search, x$node, x$doc, xpath, ns, Inf) if (!is.numeric(res)) { stop("result of type: ", sQuote(class(res)), ", not numeric", call. = FALSE) } res } #' @export xml_find_num.xml_nodeset <- function(x, xpath, ns = xml_ns(x)) { if (length(x) == 0) return(numeric()) vapply(x, function(x) xml_find_num(x, xpath = xpath, ns = ns), numeric(1)) } #' @export xml_find_num.xml_missing <- function(x, xpath, ns = xml_ns(x)) { numeric(0) } #' @export #' @rdname xml_find_all xml_find_chr <- function(x, xpath, ns = xml_ns(x)) { UseMethod("xml_find_chr") } #' @export xml_find_chr.xml_node <- function(x, xpath, ns = xml_ns(x)) { res <- .Call(xpath_search, x$node, x$doc, xpath, ns, Inf) if (!is.character(res)) { stop("result of type: ", sQuote(class(res)), ", not character", call. = FALSE) } res } #' @export xml_find_chr.xml_nodeset <- function(x, xpath, ns = xml_ns(x)) { if (length(x) == 0) return(character()) vapply(x, function(x) xml_find_chr(x, xpath = xpath, ns = ns), character(1)) } #' @export xml_find_chr.xml_missing <- function(x, xpath, ns = xml_ns(x)) { character(0) } #' @export #' @rdname xml_find_all xml_find_lgl <- function(x, xpath, ns = xml_ns(x)) { UseMethod("xml_find_lgl") } #' @export xml_find_lgl.xml_node <- function(x, xpath, ns = xml_ns(x)) { res <- .Call(xpath_search, x$node, x$doc, xpath, ns, Inf) if (!is.logical(res)) { stop("result of type: ", sQuote(class(res)), ", not logical", call. = FALSE) } res } #' @export xml_find_lgl.xml_nodeset <- function(x, xpath, ns = xml_ns(x)) { if (length(x) == 0) return(logical()) vapply(x, function(x) xml_find_lgl(x, xpath = xpath, ns = ns), logical(1)) } #' @export xml_find_lgl.xml_missing <- function(x, xpath, ns = xml_ns(x)) { logical(0) } # Deprecated functions ---------------------------------------------------- #' @rdname xml_find_all #' @usage NULL #' @export xml_find_one <- function(x, xpath, ns = xml_ns(x)) { .Deprecated("xml_find_first") UseMethod("xml_find_first") } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/R/xml_attr.R�����������������������������������������������������������������������������������0000644�0001762�0000144�00000014527�13637645657�013351� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#' Retrieve an attribute. #' #' `xml_attrs()` retrieves all attributes values as a named character #' vector, `xml_attrs() <-` or `xml_set_attrs()` sets all attribute #' values. `xml_attr()` retrieves the value of single attribute and #' `xml_attr() <-` or `xml_set_attr()` modifies its value. If the #' attribute doesn't exist, it will return `default`, which defaults to #' `NA`. `xml_has_attr()` tests if an attribute is present. #' #' @inheritParams xml_name #' @param attr Name of attribute to extract. #' @param default Default value to use when attribute is not present. #' @return `xml_attr()` returns a character vector. `NA` is used #' to represent of attributes that aren't defined. #' #' `xml_has_attr()` returns a logical vector. #' #' `xml_attrs()` returns a named character vector if `x` x is single #' node, or a list of character vectors if given a nodeset #' @export #' @examples #' x <- read_xml("<root id='1'><child id ='a' /><child id='b' d='b'/></root>") #' xml_attr(x, "id") #' xml_attr(x, "apple") #' xml_attrs(x) #' #' kids <- xml_children(x) #' kids #' xml_attr(kids, "id") #' xml_has_attr(kids, "id") #' xml_attrs(kids) #' #' # Missing attributes give missing values #' xml_attr(xml_children(x), "d") #' xml_has_attr(xml_children(x), "d") #' #' # If the document has a namespace, use the ns argument and #' # qualified attribute names #' x <- read_xml(' #' <root xmlns:b="http://bar.com" xmlns:f="http://foo.com"> #' <doc b:id="b" f:id="f" id="" /> #' </root> #' ') #' doc <- xml_children(x)[[1]] #' ns <- xml_ns(x) #' #' xml_attrs(doc) #' xml_attrs(doc, ns) #' #' # If you don't supply a ns spec, you get the first matching attribute #' xml_attr(doc, "id") #' xml_attr(doc, "b:id", ns) #' xml_attr(doc, "id", ns) #' #' # Can set a single attribute with `xml_attr() <-` or `xml_set_attr()` #' xml_attr(doc, "id") <- "one" #' xml_set_attr(doc, "id", "two") #' #' # Or set multiple attributes with `xml_attrs()` or `xml_set_attrs()` #' xml_attrs(doc) <- c("b:id" = "one", "f:id" = "two", "id" = "three") #' xml_set_attrs(doc, c("b:id" = "one", "f:id" = "two", "id" = "three")) xml_attr <- function(x, attr, ns = character(), default = NA_character_) { UseMethod("xml_attr") } #' @export xml_attr.xml_missing <- function(x, attr, ns = character(), default = NA_character_) { default } #' @export xml_attr.xml_node <- function(x, attr, ns = character(), default = NA_character_) { .Call(node_attr, x$node, attr, as.character(default), ns) } #' @export xml_attr.xml_nodeset <- function(x, attr, ns = character(), default = NA_character_) { vapply(x, xml_attr, attr = attr, default = default, ns = ns, FUN.VALUE = character(1)) } #' @export #' @rdname xml_attr xml_has_attr <- function(x, attr, ns = character()) { !is.na(xml_attr(x, attr, ns = ns)) } #' @export #' @rdname xml_attr xml_attrs <- function(x, ns = character()) { UseMethod("xml_attrs") } #' @export xml_attrs.xml_missing <- function(x, ns = character()) { NA_character_ } #' @export xml_attrs.xml_node <- function(x, ns = character()) { .Call(node_attrs, x$node, nsMap = ns) } #' @export xml_attrs.xml_nodeset <- function(x, ns = character()) { lapply(x, xml_attrs, ns = ns) } #' @param value character vector of new value. #' @rdname xml_attr #' @export `xml_attr<-` <- function(x, attr, ns = character(), value) { UseMethod("xml_attr<-") } #' @export `xml_attr<-.xml_node` <- function(x, attr, ns = character(), value) { if (is.null(value)) { .Call(node_remove_attr, x$node, attr, ns) } else { value <- as.character(value) .Call(node_set_attr, x$node, attr, value, ns) } x } #' @export `xml_attr<-.xml_nodeset` <- function(x, attr, ns = character(), value) { if (length(x) == 0) { return(x) } if (length(value) == 0) { value <- list(value) } mapply(`xml_attr<-`, x, attr = attr, value = value, SIMPLIFY = FALSE, MoreArgs = list(ns = ns)) x } #' @export `xml_attr<-.xml_missing` <- function(x, attr, ns = character(), value) { x } #' @rdname xml_attr #' @export xml_set_attr <- function(x, attr, value, ns = character()) { UseMethod("xml_set_attr") } # This function definition is used for all methods, we need to rearrange the `ns` # argument to be at the end of the set function set_attr_fun <- function(x, attr, value, ns = character()) { xml_attr(x = x, attr = attr, ns = ns) <- value } #' @export xml_set_attr.xml_node <- set_attr_fun #' @export xml_set_attr.xml_nodeset <- set_attr_fun #' @export xml_set_attr.xml_missing <- set_attr_fun #' @rdname xml_attr #' @export `xml_attrs<-` <- function(x, ns = character(), value) { UseMethod("xml_attrs<-") } #' @export `xml_attrs<-.xml_node` <- function(x, ns = character(), value) { if (!is_named(value)) { stop("`value` must be a named character vector or `NULL`", call. = FALSE) } attrs <- names(value) # as.character removes all attributes (including names) value <- stats::setNames(as.character(value), attrs) current_attrs <- names(xml_attrs(x, ns = ns)) existing <- intersect(current_attrs, attrs) new <- setdiff(attrs, current_attrs) removed <- setdiff(current_attrs, attrs) # replace existing attributes and add new ones Map(function(attr, val) { xml_attr(x, attr, ns) <- val }, attr = c(existing, new), value[c(existing, new)]) # Remove attributes which no longer exist Map(function(attr) { xml_attr(x, attr, ns) <- NULL }, attr = removed) x } #' @export `xml_attrs<-.xml_nodeset` <- function(x, ns = character(), value) { if (length(x) == 0) { return(x) } if (!is.list(ns)) { ns <- list(ns) } if (!is.list(value)) { value <- list(value) } if (!all(vapply(value, is_named, logical(1)))) { stop("`value` must be a list of named character vectors") } Map(`xml_attrs<-`, x, ns, value) x } #' @export `xml_attrs<-.xml_missing` <- function(x, ns = character(), value) { x } #' @rdname xml_attr #' @export xml_set_attrs <- function(x, value, ns = character()) { UseMethod("xml_set_attrs") } # This function definition is used for all methods, we need to rearrange the `ns` # argument to be at the end of the set function set_attrs_fun <- function(x, value, ns = character()) { xml_attrs(x = x, ns = ns) <- value } #' @export xml_set_attrs.xml_node <- set_attrs_fun #' @export xml_set_attrs.xml_nodeset <- set_attrs_fun #' @export xml_set_attrs.xml_missing <- set_attrs_fun �������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/R/xml_namespaces.R�����������������������������������������������������������������������������0000644�0001762�0000144�00000004636�13637400304�014470� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#' XML namespaces. #' #' `xml_ns` extracts all namespaces from a document, matching each #' unique namespace url with the prefix it was first associated with. Default #' namespaces are named `d1`, `d2` etc. Use `xml_ns_rename` #' to change the prefixes. Once you have a namespace object, you can pass it to #' other functions to work with fully qualified names instead of local names. #' #' @export #' @inheritParams xml_name #' @param old,... An existing xml_namespace object followed by name-value #' (old prefix-new prefix) pairs to replace. #' @return A character vector with class `xml_namespace` so the #' default display is a little nicer. #' @examples #' x <- read_xml(' #' <root> #' <doc1 xmlns = "http://foo.com"><baz /></doc1> #' <doc2 xmlns = "http://bar.com"><baz /></doc2> #' </root> #' ') #' xml_ns(x) #' #' # When there are default namespaces, it's a good idea to rename #' # them to give informative names: #' ns <- xml_ns_rename(xml_ns(x), d1 = "foo", d2 = "bar") #' ns #' #' # Now we can pass ns to other xml function to use fully qualified names #' baz <- xml_children(xml_children(x)) #' xml_name(baz) #' xml_name(baz, ns) #' #' xml_find_all(x, "//baz") #' xml_find_all(x, "//foo:baz", ns) #' #' str(as_list(x)) #' str(as_list(x, ns)) xml_ns <- function(x) { UseMethod("xml_ns") } #' @export xml_ns.xml_document <- function(x) { if (length(x) == 0) { return(character()) } stopifnot(inherits(x, "xml_document")) doc <- x$doc x <- .Call(doc_namespaces, doc) # Number default namespaces is_default <- names(x) == "" names(x)[is_default] <- paste0("d", seq_len(sum(is_default))) # Make prefixes unique names(x) <- make.unique(names(x), "") class(x) <- "xml_namespace" x } #' @export xml_ns.xml_node <- function(x) { xml_ns(xml_root(x)) } #' @export xml_ns.xml_nodeset <- function(x) { if (length(x) == 0) { return(character()) } xml_ns(x[[1]]) } #' @export xml_ns.xml_missing <- function(x) { character() } #' @export print.xml_namespace <- function(x, ...) { prefix <- format(names(x)) cat(paste0(prefix, " <-> ", x, collapse = "\n"), "\n", sep = "") } #' @export #' @rdname xml_ns xml_ns_rename <- function(old, ...) { new <- c(...) m <- match(names(new), names(old)) if (any(is.na(m))) { missing <- paste(names(new)[is.na(m)], collapse = ", ") stop("Some prefixes [", missing, "] don't already exist.", call. = FALSE) } names(old)[m] <- new old } ��������������������������������������������������������������������������������������������������xml2/NEWS.md����������������������������������������������������������������������������������������0000644�0001762�0000144�00000017462�13643425617�012257� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# xml2 1.3.1 * `read_html()` now again works with HTML files with non-ASCII encodings (#293). # xml2 1.3.0 * Removes the Rcpp dependency # xml2 1.2.5 * Fix compilation issue on macOS versions after High Sierra when not using homebrew supplied libxml2 # xml2 1.2.4 * Fix potential dangling pointer with internal `asXmlChar()` function (@michaelquinn32, #287). * `as_xml_document()` now handles cases with text nodes trailing normal nodes (#274). * `xml_add_child()` can now create nodes with a `par` attribute. These previously errored due to partial name matching of the `parent` function in the internal `create_node()` function. (@jennybc, #285) * `libxml2_version()` now returns a semantic version rather than alphanumeric version, so "2.9.10" > "2.9.9" (#277) # xml2 1.2.2 * Export S4 classes with documentation, so they can be used in other packages without Warnings (@nuest, #267) # xml2 1.2.1 ## New Features * xml2 now has a pkgdown site! <http://xml2.r-lib.org> (@jayhesselberth, #211). * Windows: upgrade to libxml2 2.9.8 * print methods now match the type of document, e.g. `read_html()` prints as "{html_document}" rather than "{xml_document}" (#227) ## Bugfixes and Miscellaneous features * Generic xml2 error are now forwarded as R errors. Previously these errors were output to stderr, so could not be suppressed (#209). * Fix for ICU 59+ defaulting to use char16_t, which is only available in C++11 (#231) * No longer uses the C connections API * Better error message when trying to run `download_xml()` without the curl package installed (#262) * xml2 classes are now registered for use with S4 by calling `setOldClass()` (#248) * Nodes with nested data type definition entities now work without crashing (#241) * Test failure fixed due to behavior change with relative paths in libxml2 2.9.9 (#245). * `read_xml()` now has a better error message when given zero length character inputs (#212). * `read_xml()` and `read_html()` now automatically check if the response succeeded before trying to read from a HTTP response (#255). * `xml_root()` can now create root nodes with namespaces (#239) * `xml_set_attr()` no longer crashes if you try to set the same namespace on the same node multiple times (#253). * `xml_set_attr()` now recycles the values if needed (#221) * `xml_structure()` gains a `file` argument, to support writing to a file rather than the console (#244). # xml2 1.2.0 ## Breaking changes * `as_list()` on `xml_document` objects did not properly include the root node in the returned list. Previous behavior can be obtained by using `as_list()[[1L]]` in place of `as_list()`. ## New Features * `download_xml()` and `download_html()` helper functions to make it easy to download files (#193). * `xml_attr()` can now set attributes with no value (#198). * `xml_serialize()` and `xml_unserialize()` now create file connections when given character input (#179). ## Bugfixes * `xml_find_first()` no longer de-duplicates results, so the results are always the same length as the inputs (as documented) (#194). * xml2 can now build using libxml2 2.7.0 * Use Rcpp symbol registration and visibility to prevent symbol conflicts on Linux * `xml_add_child()` now requires less resources to insert a node when called with `.where = 0L` (@heckendorfc, #175). * Fixed failing examples due to a change in an external resource. # xml2 1.1.1 * This is a small point release addressing installation issues found with older libxml2 versions shipped with RedHat Linux 6 / CentOS 6 (#163, #164). # xml2 1.1.0 ## New Features * `write_xml()` and `write_html()` now accept connections as well as filenames for output. (#157) * `xml_add_child()` now takes a `.where` argument specifying where to add the new children. (#138) * `as_xml()` generic function to convert R objects to xml. The most important method is for lists and enables full roundtrip support for going to and back from xml for lists and enables full roundtrip support to and from XML. (#137, #143) * `xml_new_root()` can be used to create a new document and a root node in one step (#131). * `xml_add_parent()` inserts a new node between the node and its parent (#129) * Add `xml_validate()` to validate a document against an xml schema (#31, @jeroenooms). * Export `xml2_types.h` to allow for extension packages such as xslt. * `xml_comment()` allows you to add comment nodes to a document. (#111) * `xml_cdata()` allows you to add CDATA nodes to a document. (#128) * Add `xml_set_text()` and `xml_set_name()` equivalent to `xml_text<-` and `xml_name<-`. (#130). * Add `xml_set_attr()` and `xml_set_attrs()` equivalent to `xml_attr<-` and `xml_attrs<-`. (#109, #130) * Add `write_html()` method (#133). ## Bugfixes * `xml_new_document()` now explicitly sets the encoding (default UTF-8) (#142) * Document formatting options for `write_xml()` (#132) * Add missing methods for xml_missing objects. (#134) * Bugfix for xml_length.xml_nodeset that caused it to fail unconditionally. (#140) * `is.na()` now returns `TRUE` for `xml_missing` objects. (#139) * Trim non-breaking spaces in `xml_text(trim = TRUE)` (#151). * Allow setting non-character attributes (values are coerced to characters). (@sjp, #117, #122). * Fixed return value in call to vapply in xml_integer.xml_nodeset. (@ddiez, #146, #147). * Allow docs missing a root element to be created and printed. (@sjp, #126, #121). * xml_add_* methods now return invisibly. (@sjp, #124) * `as_list()` now preserves element names when attributes exist, and escapes XML attributes that conflict with special R attributes (@peterfoley, #115). # xml2 1.0.0 * All C++ functions now use `checked_get()` instead of `get()` where possible, so NULL XPtrs properly throw an error rather than crashing. (@jimhester, #101, #104). * `xml_integer()` and `xml_double()` functions to make it easy to extract integer and double text from nodes (@jimhester, #97, #99). * xml2 now supports modification and creation of XML nodes. New functions `xml_new_document()`, `xml_new_child()`, `xml_new_sibling()`, `xml_set_namespace()`, , `xml_remove()`, `xml_replace()`, `xml_root()` and replacement methods for `xml_name()`, `xml_attr()`, `xml_attrs()` and `xml_text()` (@jimhester, #9 #76) * `xml_ns()` now keeps namespace prefixes that point to the same URI (@jimhester, #35, #95). * `read_xml()` and `read_html()` methods added for `httr::response()` objects. (@jimhester, #63, #93) * `xml_child()` function to make selecting children a little easier (@jimhester, #23, #94) * `xml_find_one()` has been deprecated in favor of `xml_find_first()` (@jimhester, #58, #92) * `xml_read()` functions now default to passing the document's namespace object. Namespace definitions can now be removed as well as added and `xml_ns_strip()` added to remove all default namespaces from a document. (@jimhester, #28, #89) * `xml_read()` gains a `options` argument to control all available parsing options, including `HUGE` to turn off limits for parsing very large documents and now drops blank text nodes by default, mimicking default behavior of XML package. (@jimhester, #49, #62, #85, #88) * `xml_write()` expands the path on filenames, so directories can be specified with '~/' (@jimhester, #86, #80) * `xml_find_one()` now returns a 'xml_missing' node object if there are 0 matches (@jimhester, #55, #53, hadley/rvest#82). * `xml_find_num()`, `xml_find_chr()`, `xml_find_lgl()` functions added to return numeric, character and logical results from XPath expressions. (@jimhester, #55) * `xml_name()` and `xml_text()` always correctly encode returned value as UTF-8 (#54). # xml2 0.1.2 * Improved configure script - now works again on R-devel on windows. * Compiles with older versions of libxml2., # xml2 0.1.1 * Make configure script more cross platform. * Add `xml_length()` to count the number of children (#32). ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/MD5��������������������������������������������������������������������������������������������0000644�0001762�0000144�00000015513�13643540352�011456� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������be45324dd26240636614b51d2a614ebb *DESCRIPTION 4ef043cf1dc65acac5b043732b3b6ae4 *NAMESPACE 00e6f313be1921d3702c349ce6848752 *NEWS.md e666e6c65a95b36309a45087dbc3c200 *R/S4.R 4c50d1baef6a82688f67ff03b92d35ef *R/as_list.R 4e8cbecbe4bf193d18286a4c941f9475 *R/as_xml_document.R 537c2312c93e9453248fcbd310c024b9 *R/classes.R c27e822f5edbacba5c565b6dfd5e5ec0 *R/init.R 1543aa35645349a951aad3364b1949be *R/paths.R bc52d43c1fa60beaf4c26fb0907f3c5b *R/utils.R db90ce5ddc489be7ced18ce9527e0938 *R/xml_attr.R a379dfa3fcc6d875565cc69353177ed6 *R/xml_children.R 3b42ed768976dbd3e1acc9103dd8f7cf *R/xml_find.R f55565b0c494a126a91a34a7fbf7e29b *R/xml_modify.R 29df357d427b973fb46b010d4e7cc838 *R/xml_name.R 55979f8f8062620fadad2f23a5e54b26 *R/xml_namespaces.R fc877a6c1a4a994563a6eef80de8538c *R/xml_parse.R a8b6f03e5138039a019139c44b53c259 *R/xml_path.R 8b6f2d8eb51765092d2e1ef307277f1b *R/xml_schema.R f36d8a7891bff1992738a6ee396e3182 *R/xml_serialize.R 608fc39d49a0d56dd0951750252395dc *R/xml_structure.R 0900d27cd9b81e462d5dd2f6e27b8486 *R/xml_text.R 81eb98ca4be75fa876c398bd846c0c32 *R/xml_type.R 6c2b17e1e15313511a887fbab06b68ad *R/xml_url.R ad8ee249569e2c54ca16e64e073245a4 *R/xml_write.R ba02edba719f666ae5dffeb962b215df *R/zzz.R 453981224aba562298251d13badda722 *README.md 8289d020b6bda291a6bc14cd17d82972 *build/vignette.rds e10c630b06c63257f3e4b29478922fb1 *build/xml2.pdf 6071edd604dbeb75308cfbedc7790398 *cleanup 0ca14a6efb702e7a9651afe003025d74 *configure d41d8cd98f00b204e9800998ecf8427e *configure.win 71e4c691330a0c3874257f80e782e091 *inst/doc/modification.R 59426c1676cc6681db7e45ca88f94357 *inst/doc/modification.Rmd 4f9168f2d0c5c1d2e630c1af1ca1f783 *inst/doc/modification.html f8254da868eddec64a4768db0a43ae14 *inst/extdata/cd_catalog.xml aa42c312677d8bd431c9f6055bacc5a2 *inst/extdata/order-doc.xml d815540b17662ddb93faa91d78ba0e5f *inst/extdata/order-schema.xml 3d75cb054004ba36cf5bb4cac44eb27c *inst/extdata/r-project.html 9ffbbf76ff3d8cf21ba9922f4ab9a1de *inst/include/xml2_types.h 890574119d12217213ddc7f078ec66b4 *man/as_list.Rd e5c2a742f2de7359c54ff9039d2e119e *man/as_xml_document.Rd eef7c30dfc2cbaea49edb9c8a457ee15 *man/download_xml.Rd 1d048db5b4a20d0dc6971e05433c4898 *man/oldclass.Rd fe0e8292d02a7cf641570b3e7dabefa5 *man/read_xml.Rd f279c9395e6a6f9e309daa4aa11ed3f0 *man/url_absolute.Rd adc1d00522ecda5e39328ff774e08469 *man/url_escape.Rd 445e678dcf4634d56ad824b0b55fc8ab *man/url_parse.Rd 61eea7e64383e1a35df2e59ebc441d1c *man/write_xml.Rd f614d1bf7ef5a8d72cd8a1088f9fbf16 *man/xml2_example.Rd efc8cf920389740f0742f9fb9d3abb58 *man/xml_attr.Rd 0a15f65df35d04c730b7744233ad28c7 *man/xml_cdata.Rd 47117a818845c729c102587d30dfe908 *man/xml_children.Rd eec4938beaf42ddbe1764fbe20a83172 *man/xml_comment.Rd 5db6b02f83879ca57feb9e18574ce9d5 *man/xml_dtd.Rd 3a4be0c2cce98e21eef9f731b7b43c0c *man/xml_find_all.Rd 006d39e67f0ca9f1285b1cb03dc86ef9 *man/xml_missing.Rd 245103ba404c1977e8e94137044312a6 *man/xml_name.Rd 5346e5d651907f84348245e9f33711fe *man/xml_new_document.Rd 0a794285d88cda5c3ddd89aa35f76d12 *man/xml_ns.Rd ce6906ae564f92989f5f34954d61baac *man/xml_ns_strip.Rd dbf2a353f094ffb6ecd83057cbc0f8d5 *man/xml_path.Rd 87a46a25bb7ebcdb9b79ba0ef3e9c2c8 *man/xml_replace.Rd f0f5b4f10db8d40cb1c1da96732fea87 *man/xml_serialize.Rd a9f5428f85b307c4c9fc57a0c2335e81 *man/xml_set_namespace.Rd ba07ca2c3b9501050fd045669eb13f62 *man/xml_structure.Rd 516d4923a3e271bed7d1c4ea9a1aa6e2 *man/xml_text.Rd 38ba6b30dd14531181f367e7cf8d5733 *man/xml_type.Rd 376d10c9316a4b239468b2bff8c9b0c2 *man/xml_url.Rd f2db32908ff0cdc1fa672f77eb5c5e7b *man/xml_validate.Rd ea947a311b45dd48a131a29570d43265 *src/Makevars.in 017a968e14d691d667ca3a06693a5d78 *src/Makevars.win 520c2eee421cefd566346cfcb1319587 *src/connection.cpp 5e1d636b082968e0fc36e550fa717099 *src/connection.h 8ebd7cc3cdd0f50f258be7423b6dbea1 *src/init.c 5ac0575a09afc52b2f80bf89c138f549 *src/xml2_doc.cpp ab9884c004dfa9d3821cd3fb265cffd1 *src/xml2_init.cpp 1253d3d96d74f3b07b7f88e063124848 *src/xml2_namespace.cpp c2b0b910a215464200861cf65b970a05 *src/xml2_node.cpp 20d5f8d664d015d8d9213e640152b19a *src/xml2_output.cpp 5d8619e181ee20b058195012c2ab7d6e *src/xml2_schema.cpp 6c32da6997f59590e214c7d73d5c728f *src/xml2_url.cpp 2e4637dc959cfd3e82b344d7ea143729 *src/xml2_utils.h 109742f9297edb7673943968065e513f *src/xml2_xpath.cpp ae0f130cf638898b6e81d02431bc3b1c *tests/testthat.R 85a9b9931ae7f8b80c98bc04692dc034 *tests/testthat/helper-version.R 06cbfa014c1b836d0dee95ed66cbcc90 *tests/testthat/helper.R 88882b509327ad5661e9e8b8ca7805d4 *tests/testthat/lego.html.bz2 1269f1bd55f2272ef97d7f0900edee94 *tests/testthat/ns-multiple-aliases.xml 188d2702e42e6f3cb3b4d36779c6f0cc *tests/testthat/ns-multiple-default.xml cf756b5e4205cd7b096ef03475ab2571 *tests/testthat/ns-multiple-prefix.xml 5e2eed6052aeceba49eb114479f6694a *tests/testthat/ns-multiple.xml b2e3f18f3d068252f9dbb073b92a437a *tests/testthat/output/html_structure.txt 7c32726f297cc4ac9f292e6199c66ddf *tests/testthat/output/print-xml_document.txt a95fdeb250434809199a83c29de50c19 *tests/testthat/output/print-xml_node.txt 1134e7618c0aa64eadd06fa2d4906b21 *tests/testthat/output/print-xml_nodeset.txt d6b1604dd0089c1be5d6e3d72f3095f9 *tests/testthat/records.dtd 9c0ac6aa9f95de3c13023ded7befba62 *tests/testthat/records.xml cde9be4ab9103a9c2766d2f071832c4f *tests/testthat/test-as_list.R 95aa0fe5baaf0ce740f8d885a3ed89df *tests/testthat/test-as_xml_document.R f11f06505ed7203653dab06a56075c1f *tests/testthat/test-cdata.R ba04389bf1231d1edbb7e4beb014f04d *tests/testthat/test-comment.R f16f5a677e6e647de277e7b0f4cf9e44 *tests/testthat/test-dtd.R 64d0872b75fa98871ab36d602ff390a7 *tests/testthat/test-format.R b63bd89927e0ebb476d87b659297a68e *tests/testthat/test-modify-xml.R a304b847caf029fbfc436f34a371f553 *tests/testthat/test-namespaces.R f9040e9a15fc995b1f187caaff3584ba *tests/testthat/test-null.R ff777492a9390829bea82e9a588153a6 *tests/testthat/test-print.R 862091fadd872a33ffd1dce0dbac3e0c *tests/testthat/test-read-xml.R a6d0b66b125036ec9913ad60c214c663 *tests/testthat/test-url.R 77c654f21a95b5359f28d7db10760021 *tests/testthat/test-write_xml.R fb3d5beea0df836135576cc80a127b40 *tests/testthat/test-xml_attrs.R 4b2c4bd75e825c07a5760f3260911c7c *tests/testthat/test-xml_children.R 8cd9416b142c7c16dd4844e85e5702e2 *tests/testthat/test-xml_find.R 304de1b3d4405f8fa282166bc2cb540c *tests/testthat/test-xml_missing.R c161bbcd94441a4a86ed74a693d05e28 *tests/testthat/test-xml_name.R 34489e0c5773c8892b2fdb6ddac27f4d *tests/testthat/test-xml_nodeset.R fbd1f73cd0685dbb07384785bb10100f *tests/testthat/test-xml_parse.R 1d96bc26d0d47fd2f9c0a88279957f37 *tests/testthat/test-xml_schema.R 1f19b1f9753ee920d8927bdabf78eb05 *tests/testthat/test-xml_serialize.R 70041cbd2099e626a390759c2c2c3e86 *tests/testthat/test-xml_structure.R 116ac76436068562dbf9754f5a7e4263 *tests/testthat/test-xml_text.R 3e59936d5eff44f9725265ab5a253510 *tools/winlibs.R 59426c1676cc6681db7e45ca88f94357 *vignettes/modification.Rmd 4b198a3f236c08d15f90d8a66a08bd04 *vignettes/releases/xml2-1.1.1.Rmd �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/inst/������������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�13643426274�012124� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/inst/doc/��������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�13643426274�012671� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/inst/doc/modification.R������������������������������������������������������������������������0000644�0001762�0000144�00000006000�13643426273�015454� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## ---- echo = FALSE, message = FALSE------------------------------------------- knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(xml2) library(magrittr) ## ----------------------------------------------------------------------------- x <- read_xml("<p>This is some <b>text</b>. This is more.</p>") xml_text(x) xml_text(x) <- "This is some other text." xml_text(x) # You can avoid this by explicitly selecting the text node. x <- read_xml("<p>This is some text. This is <b>bold!</b></p>") text_only <- xml_find_all(x, "//text()") xml_text(text_only) <- c("This is some other text. ", "Still bold!") xml_text(x) xml_structure(x) ## ----------------------------------------------------------------------------- x <- read_xml("<a href='invalid!'>xml2</a>") xml_attr(x, "href") xml_attr(x, "href") <- "https://github.com/r-lib/xml2" xml_attr(x, "href") xml_attrs(x) <- c(id = "xml2", href = "https://github.com/r-lib/xml2") xml_attrs(x) x xml_attrs(x) <- NULL x # Namespaces are added with as a xmlns or xmlns:prefix attribute xml_attr(x, "xmlns") <- "http://foo" x xml_attr(x, "xmlns:bar") <- "http://bar" x ## ----------------------------------------------------------------------------- x <- read_xml("<a><b/></a>") x xml_name(x) xml_name(x) <- "c" x ## ----------------------------------------------------------------------------- x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_replace(t1, t3) x ## ----------------------------------------------------------------------------- x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_add_sibling(t1, t3) x xml_add_sibling(t3, t1, where = "before") x ## ----------------------------------------------------------------------------- x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_add_child(t1, t3) x xml_add_child(t1, read_xml("<test/>")) x ## ----------------------------------------------------------------------------- x <- read_xml("<foo><bar><baz/></bar></foo>") x1 <- x %>% xml_children() %>% .[[1]] x2 <- x1 %>% xml_children() %>% .[[1]] xml_remove(x1) rm(x1) gc() x2 ## ----------------------------------------------------------------------------- x <- read_xml("<a><b /><b><b /></b></a>") bees <- xml_find_all(x, "//b") xml_remove(xml_child(x), free = TRUE) # bees[[1]] is no longer valid!!! rm(bees) gc() ## ----------------------------------------------------------------------------- d <- xml_new_root("sld", xmlns = "http://www.o.net/sld", "xmlns:ogc" = "http://www.o.net/ogc", "xmlns:se" = "http://www.o.net/se", version = "1.1.0") %>% xml_add_child("layer") %>% xml_add_child("se:Name", "My Layer") %>% xml_root() d xml2/inst/doc/modification.Rmd����������������������������������������������������������������������0000644�0001762�0000144�00000011756�13631515545�016011� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������--- title: "Node Modification" author: "Jim Hester" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Node Modification} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, echo = FALSE, message = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(xml2) library(magrittr) ``` # Modifying Existing XML Modifying existing XML can be done in xml2 by using the replacement functions of the accessors. They all have methods for both individual `xml_node` objects as well as `xml_nodeset` objects. If a vector of values is provided it is applied piecewise over the nodeset, otherwise the value is recycled. ## Text Modification ## Text modification only happens on text nodes. If a given node has more than one text node only the first will be affected. If you want to modify additional text nodes you need to select them explicitly with `/text()`. ```{r} x <- read_xml("<p>This is some <b>text</b>. This is more.</p>") xml_text(x) xml_text(x) <- "This is some other text." xml_text(x) # You can avoid this by explicitly selecting the text node. x <- read_xml("<p>This is some text. This is <b>bold!</b></p>") text_only <- xml_find_all(x, "//text()") xml_text(text_only) <- c("This is some other text. ", "Still bold!") xml_text(x) xml_structure(x) ``` ## Attribute and Namespace Definition Modification ## Attributes and namespace definitions are modified one at a time with `xml_attr()` or all at once with `xml_attrs()`. In both cases using `NULL` as the value will remove the attribute completely. ```{r} x <- read_xml("<a href='invalid!'>xml2</a>") xml_attr(x, "href") xml_attr(x, "href") <- "https://github.com/r-lib/xml2" xml_attr(x, "href") xml_attrs(x) <- c(id = "xml2", href = "https://github.com/r-lib/xml2") xml_attrs(x) x xml_attrs(x) <- NULL x # Namespaces are added with as a xmlns or xmlns:prefix attribute xml_attr(x, "xmlns") <- "http://foo" x xml_attr(x, "xmlns:bar") <- "http://bar" x ``` ## Name Modification ## Node names are modified with `xml_name()`. ```{r} x <- read_xml("<a><b/></a>") x xml_name(x) xml_name(x) <- "c" x ``` # Node modification # All of these functions have a `.copy` argument. If this is set to `FALSE` they will remove the new node from its location before inserting it into the new location. Otherwise they make a copy of the node before insertion. ## Replacing existing nodes ## ```{r} x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_replace(t1, t3) x ``` ## Add a sibling ## ```{r} x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_add_sibling(t1, t3) x xml_add_sibling(t3, t1, where = "before") x ``` ## Add a child ## ```{r} x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>") children <- xml_children(x) t1 <- children[[1]] t2 <- children[[2]] t3 <- xml_children(children[[2]])[[1]] xml_add_child(t1, t3) x xml_add_child(t1, read_xml("<test/>")) x ``` ## Removing nodes ## The `xml_remove()` can be used to remove a node (and its children) from a tree. The default behavior is to unlink the node from the tree, but does _not_ free the memory for the node, so R objects pointing to the node are still valid. This allows code like the following to work without crashing R ```{r} x <- read_xml("<foo><bar><baz/></bar></foo>") x1 <- x %>% xml_children() %>% .[[1]] x2 <- x1 %>% xml_children() %>% .[[1]] xml_remove(x1) rm(x1) gc() x2 ``` If you are not planning on referencing these nodes again this memory is wasted. Calling `xml_remove(free = TRUE)` will remove the nodes _and_ free the memory used to store them. **Note** In this case _any_ node which previously pointed to the node or its children will instead be pointing to free memory and may cause R to crash. xml2 can't figure this out for you, so it's your responsibility to remove any objects which are no longer valid. In particular `xml_find_*()` results are easy to overlook, for example ```{r} x <- read_xml("<a><b /><b><b /></b></a>") bees <- xml_find_all(x, "//b") xml_remove(xml_child(x), free = TRUE) # bees[[1]] is no longer valid!!! rm(bees) gc() ``` ## Namespaces ## We want to construct a document with the following namespace layout. (From http://stackoverflow.com/questions/32939229/creating-xml-in-r-with-namespaces/32941524#32941524). ```xml <?xml version = "1.0" encoding="UTF-8"?> <sld xmlns="http://www.o.net/sld" xmlns:ogc="http://www.o.net/ogc" xmlns:se="http://www.o.net/se" version="1.1.0" > <layer> <se:Name>My Layer</se:Name> </layer> </sld> ``` ```{r} d <- xml_new_root("sld", xmlns = "http://www.o.net/sld", "xmlns:ogc" = "http://www.o.net/ogc", "xmlns:se" = "http://www.o.net/se", version = "1.1.0") %>% xml_add_child("layer") %>% xml_add_child("se:Name", "My Layer") %>% xml_root() d ``` ������������������xml2/inst/doc/modification.html���������������������������������������������������������������������0000644�0001762�0000144�00000076024�13643426274�016235� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="generator" content="pandoc" /> <meta http-equiv="X-UA-Compatible" content="IE=EDGE" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="author" content="Jim Hester" /> <meta name="date" content="2020-04-08" /> <title>Node Modification

Node Modification

Jim Hester

2020-04-08

Modifying Existing XML

Modifying existing XML can be done in xml2 by using the replacement functions of the accessors. They all have methods for both individual xml_node objects as well as xml_nodeset objects. If a vector of values is provided it is applied piecewise over the nodeset, otherwise the value is recycled.

Text Modification

Text modification only happens on text nodes. If a given node has more than one text node only the first will be affected. If you want to modify additional text nodes you need to select them explicitly with /text().

x <- read_xml("<p>This is some <b>text</b>. This is more.</p>")
xml_text(x)
#> [1] "This is some text. This is more."

xml_text(x) <- "This is some other text."
xml_text(x)
#> [1] "This is some other text.text. This is more."

# You can avoid this by explicitly selecting the text node.
x <- read_xml("<p>This is some text. This is <b>bold!</b></p>")
text_only <- xml_find_all(x, "//text()")

xml_text(text_only) <- c("This is some other text. ", "Still bold!")
xml_text(x)
#> [1] "This is some other text. Still bold!"
xml_structure(x)
#> <p>
#>   {text}
#>   <b>
#>     {text}

Attribute and Namespace Definition Modification

Attributes and namespace definitions are modified one at a time with xml_attr() or all at once with xml_attrs(). In both cases using NULL as the value will remove the attribute completely.

x <- read_xml("<a href='invalid!'>xml2</a>")
xml_attr(x, "href")
#> [1] "invalid!"

xml_attr(x, "href") <- "https://github.com/r-lib/xml2"
xml_attr(x, "href")
#> [1] "https://github.com/r-lib/xml2"

xml_attrs(x) <- c(id = "xml2", href = "https://github.com/r-lib/xml2")
xml_attrs(x)
#>                            href                              id 
#> "https://github.com/r-lib/xml2"                          "xml2"
x
#> {xml_document}
#> <a href="https://github.com/r-lib/xml2" id="xml2">

xml_attrs(x) <- NULL
x
#> {xml_document}
#> <a>

# Namespaces are added with as a xmlns or xmlns:prefix attribute
xml_attr(x, "xmlns") <- "http://foo"
x
#> {xml_document}
#> <a xmlns="http://foo">

xml_attr(x, "xmlns:bar") <- "http://bar"
x
#> {xml_document}
#> <a xmlns="http://foo" xmlns:bar="http://bar">

Name Modification

Node names are modified with xml_name().

x <- read_xml("<a><b/></a>")
x
#> {xml_document}
#> <a>
#> [1] <b/>
xml_name(x)
#> [1] "a"
xml_name(x) <- "c"
x
#> {xml_document}
#> <c>
#> [1] <b/>

Node modification

All of these functions have a .copy argument. If this is set to FALSE they will remove the new node from its location before inserting it into the new location. Otherwise they make a copy of the node before insertion.

Replacing existing nodes

x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>")
children <- xml_children(x)
t1 <- children[[1]]
t2 <- children[[2]]
t3 <- xml_children(children[[2]])[[1]]

xml_replace(t1, t3)
#> {xml_node}
#> <child>
x
#> {xml_document}
#> <parent>
#> [1] <child>3</child>
#> [2] <child>2<child>3</child></child>

Add a sibling

x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>")
children <- xml_children(x)
t1 <- children[[1]]
t2 <- children[[2]]
t3 <- xml_children(children[[2]])[[1]]

xml_add_sibling(t1, t3)
x
#> {xml_document}
#> <parent>
#> [1] <child>1</child>
#> [2] <child>3</child>
#> [3] <child>2<child>3</child></child>

xml_add_sibling(t3, t1, where = "before")
x
#> {xml_document}
#> <parent>
#> [1] <child>1</child>
#> [2] <child>3</child>
#> [3] <child>2<child>3</child><child>1</child></child>

Add a child

x <- read_xml("<parent><child>1</child><child>2<child>3</child></child></parent>")
children <- xml_children(x)
t1 <- children[[1]]
t2 <- children[[2]]
t3 <- xml_children(children[[2]])[[1]]

xml_add_child(t1, t3)
x
#> {xml_document}
#> <parent>
#> [1] <child>1<child>3</child></child>
#> [2] <child>2<child>3</child></child>

xml_add_child(t1, read_xml("<test/>"))
x
#> {xml_document}
#> <parent>
#> [1] <child>1<child>3</child><test/></child>
#> [2] <child>2<child>3</child></child>

Removing nodes

The xml_remove() can be used to remove a node (and its children) from a tree. The default behavior is to unlink the node from the tree, but does not free the memory for the node, so R objects pointing to the node are still valid.

This allows code like the following to work without crashing R

x <- read_xml("<foo><bar><baz/></bar></foo>")
x1 <- x %>% xml_children() %>% .[[1]]
x2 <- x1 %>% xml_children() %>% .[[1]]

xml_remove(x1)
rm(x1)
gc()
#>           used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
#> Ncells  572101 30.6    1275621 68.2         NA  1272531 68.0
#> Vcells 1100538  8.4    8388608 64.0      32768  2035739 15.6

x2
#> {xml_node}
#> <baz>

If you are not planning on referencing these nodes again this memory is wasted. Calling xml_remove(free = TRUE) will remove the nodes and free the memory used to store them. Note In this case any node which previously pointed to the node or its children will instead be pointing to free memory and may cause R to crash. xml2 can’t figure this out for you, so it’s your responsibility to remove any objects which are no longer valid.

In particular xml_find_*() results are easy to overlook, for example

x <- read_xml("<a><b /><b><b /></b></a>")
bees <- xml_find_all(x, "//b")
xml_remove(xml_child(x), free = TRUE)
# bees[[1]] is no longer valid!!!
rm(bees)
gc()
#>           used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
#> Ncells  572148 30.6    1275621 68.2         NA  1272531 68.0
#> Vcells 1100589  8.4    8388608 64.0      32768  2035739 15.6

Namespaces

We want to construct a document with the following namespace layout. (From http://stackoverflow.com/questions/32939229/creating-xml-in-r-with-namespaces/32941524#32941524).

<?xml version = "1.0" encoding="UTF-8"?>
<sld xmlns="http://www.o.net/sld"
     xmlns:ogc="http://www.o.net/ogc"
     xmlns:se="http://www.o.net/se"
     version="1.1.0" >
<layer>
<se:Name>My Layer</se:Name>
</layer>
</sld>
d <- xml_new_root("sld",
    xmlns = "http://www.o.net/sld",
    "xmlns:ogc" = "http://www.o.net/ogc",
    "xmlns:se" = "http://www.o.net/se",
    version = "1.1.0") %>%
  xml_add_child("layer") %>%
  xml_add_child("se:Name", "My Layer") %>%
  xml_root()

d
#> {xml_document}
#> <sld version="1.1.0" xmlns="http://www.o.net/sld" xmlns:ogc="http://www.o.net/ogc" xmlns:se="http://www.o.net/se">
#> [1] <layer>\n  <se:Name>My Layer</se:Name>\n</layer>
xml2/inst/include/0000755000176200001440000000000013637376334013553 5ustar liggesusersxml2/inst/include/xml2_types.h0000644000176200001440000000261513637376334016036 0ustar liggesusers#ifndef __XML2_XML2_TYPES__ #define __XML2_XML2_TYPES__ #include #define R_NO_REMAP #include template class XPtr { protected: SEXP data_; public: XPtr(SEXP x) : data_(x) { if (TYPEOF(data_) != EXTPTRSXP) { Rf_error("Expecting an external pointer: [type=%s]", Rf_type2char(TYPEOF(data_))); } R_PreserveObject(data_); } XPtr(T* p) { data_ = R_MakeExternalPtr((void *) p, R_NilValue, R_NilValue); } operator SEXP() const { return data_; } T* get() const { return (T*)(R_ExternalPtrAddr(data_)); } T* checked_get() const { T* ptr = get(); if (ptr == NULL) { Rf_error("external pointer is not valid"); } return ptr; } operator T*() { return checked_get(); } T* operator->() const { return checked_get(); } ~XPtr() { R_ReleaseObject(data_); } }; class XPtrDoc : public ::XPtr { static void finalizeXPtrDoc(SEXP p) { if (TYPEOF(p) != EXTPTRSXP) { return; } xmlDoc* ptr = (xmlDoc*) R_ExternalPtrAddr(p); if (ptr == NULL) { return; } R_ClearExternalPtr(p); xmlFreeDoc(ptr); } public: XPtrDoc(xmlDoc* p) : ::XPtr(p) { R_RegisterCFinalizerEx(data_, finalizeXPtrDoc, (Rboolean) false); } XPtrDoc(SEXP x) : ::XPtr(x) {} }; typedef ::XPtr XPtrNode; typedef ::XPtr XPtrNs; #endif xml2/inst/extdata/0000755000176200001440000000000013516067254013554 5ustar liggesusersxml2/inst/extdata/order-schema.xml0000644000176200001440000000461613516067254016656 0ustar liggesusers Purchase order schema for Example.com. Copyright 2000 Example.com. All rights reserved. Purchase order schema for Example.Microsoft.com. Copyright 2001 Example.Microsoft.com. All rights reserved. Application info. xml2/inst/extdata/cd_catalog.xml0000644000176200001440000001173013516067254016360 0ustar liggesusers Empire Burlesque Bob Dylan USA Columbia 10.90 1985 Hide your heart Bonnie Tylor UK CBS Records 9.90 1988 Greatest Hits Dolly Parton USA RCA 9.90 1982 Still got the blues Gary More UK Virgin redords 10.20 1990 Eros Eros Ramazzotti EU BMG 9.90 1997 One night only Bee Gees UK Polydor 10.90 1998 Sylvias Mother Dr.Hook UK CBS 8.10 1973 Maggie May Rod Stewart UK Pickwick 8.50 1990 Romanza Andrea Bocelli EU Polydor 10.80 1996 When a man loves a woman Percy Sledge USA Atlantic 8.70 1987 Black angel Savage Rose EU Mega 10.90 1995 1999 Grammy Nominees Many USA Grammy 10.20 1999 For the good times Kenny Rogers UK Mucik Master 8.70 1995 Big Willie style Will Smith USA Columbia 9.90 1997 Tupelo Honey Van Morrison UK Polydor 8.20 1971 Soulsville Jorn Hoel Norway WEA 7.90 1996 The very best of Cat Stevens UK Island 8.90 1990 Stop Sam Brown UK A and M 8.90 1988 Bridge of Spies T`Pau UK Siren 7.90 1987 Private Dancer Tina Turner UK Capitol 8.90 1983 Midt om natten Kim Larsen EU Medley 7.80 1983 Pavarotti Gala Concert Luciano Pavarotti UK DECCA 9.90 1991 The dock of the bay Otis Redding USA Atlantic 7.90 1987 Picture book Simply Red EU Elektra 7.20 1985 Red The Communards UK London 7.80 1987 Unchain my heart Joe Cocker USA EMI 8.20 1987 xml2/inst/extdata/r-project.html0000644000176200001440000001160113516067254016346 0ustar liggesusers R: The R Project for Statistical Computing

The R Project for Statistical Computing

Getting Started

R is a free software environment for statistical computing and graphics. It compiles and runs on a wide variety of UNIX platforms, Windows and MacOS. To download R, please choose your preferred CRAN mirror.

If you have questions about R like how to download and install the software, or what the license terms are, please read our answers to frequently asked questions before you send an email.

News

  • R 3.2.0 (Full of Ingredients) prerelease versions will appear starting March 19. Final release is scheduled for 2015-04-16.

  • R version 3.1.3 (Smooth Sidewalk) has been released on 2015-03-09.

  • The R Journal Volume 6/2 is available.

  • R version 3.1.2 (Pumpkin Helmet) has been released on 2014-10-31.

  • useR! 2015, will take place at the University of Aalborg, Denmark, June 30 - July 3, 2015.

  • useR! 2014, took place at the University of California, Los Angeles, USA June 30 - July 3, 2014.

xml2/inst/extdata/order-doc.xml0000644000176200001440000000200013516067254016144 0ustar liggesusers Alice Smith 123 Maple Street Mill Valley CA 90952 Robert Smith 8 Oak Avenue Old Town PA 95819 Hurry, my lawn is going wild! Lawnmower 1 148.95 Confirm this is electric Baby Monitor 1 39.98 1999-05-21 xml2/cleanup0000755000176200001440000000003513643426277012525 0ustar liggesusers#!/bin/sh rm -f src/Makevars xml2/configure0000755000176200001440000000612313643426277013063 0ustar liggesusers#!/bin/sh # Anticonf (tm) script by Jeroen Ooms (2015) # This script will query 'pkg-config' for the required cflags and ldflags. # If pkg-config is unavailable or does not find the library, try setting # INCLUDE_DIR and LIB_DIR manually via e.g: # R CMD INSTALL --configure-vars='INCLUDE_DIR=/.../include LIB_DIR=/.../lib' # Library settings PKG_CONFIG_NAME="libxml-2.0" PKG_DEB_NAME="libxml2-dev" PKG_RPM_NAME="libxml2-devel" PKG_CSW_NAME="libxml2_dev" PKG_TEST_HEADER="" PKG_LIBS="-lxml2" OS_TYPE=`uname -s` OS_VERSION=`uname -r | cut -d '.' -f 1` # Note that cflags may be empty in case of success if [ "$INCLUDE_DIR" ] || [ "$LIB_DIR" ]; then echo "Found INCLUDE_DIR and/or LIB_DIR!" PKG_CFLAGS="-I$INCLUDE_DIR $PKG_CFLAGS" PKG_LIBS="-L$LIB_DIR $PKG_LIBS" else # Use xml2-config if available xml2-config --version >/dev/null 2>&1 if [ $? -eq 0 ]; then PKGCONFIG_CFLAGS=`xml2-config --cflags` PKGCONFIG_LIBS=`xml2-config --libs` # MacOS versions El Capitan and later ship a xml2-config which appends `xcrun # --show-sdk-path` to the xml2-config. So we remove it if it is present. # (https://stat.ethz.ch/pipermail/r-sig-mac/2016-September/012046.html) if [ "$OS_TYPE" = "Darwin" ] && [ "$OS_VERSION" -gt "13" ] && [ "$OS_VERSION" -lt "17" ]; then PKGCONFIG_CFLAGS=`echo $PKGCONFIG_CFLAGS | perl -pe "s{\Q\`xcrun -show-sdk-path\`\E}{}"` PKGCONFIG_LIBS=`echo $PKGCONFIG_LIBS | perl -pe "s{\Q\`xcrun -show-sdk-path\`\E}{}"` fi else pkg-config --version >/dev/null 2>&1 if [ $? -eq 0 ]; then PKGCONFIG_CFLAGS=`pkg-config --cflags $PKG_CONFIG_NAME` PKGCONFIG_LIBS=`pkg-config --libs $PKG_CONFIG_NAME` fi fi if [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then echo "Found pkg-config cflags and libs!" PKG_CFLAGS=${PKGCONFIG_CFLAGS} PKG_LIBS=${PKGCONFIG_LIBS} fi fi # Find compiler CC=`${R_HOME}/bin/R CMD config CC` CFLAGS=`${R_HOME}/bin/R CMD config CFLAGS` CPPFLAGS=`${R_HOME}/bin/R CMD config CPPFLAGS` # For debugging echo "Using PKG_CFLAGS=$PKG_CFLAGS" echo "Using PKG_LIBS=$PKG_LIBS" # Test configuration echo "#include $PKG_TEST_HEADER" | ${CC} ${CPPFLAGS} ${PKG_CFLAGS} ${CFLAGS} -E -xc - >/dev/null 2>&1 || R_CONFIG_ERROR=1; # Customize the error if [ $R_CONFIG_ERROR ]; then echo "------------------------- ANTICONF ERROR ---------------------------" echo "Configuration failed because $PKG_CONFIG_NAME was not found. Try installing:" echo " * deb: $PKG_DEB_NAME (Debian, Ubuntu, etc)" echo " * rpm: $PKG_RPM_NAME (Fedora, CentOS, RHEL)" echo " * csw: $PKG_CSW_NAME (Solaris)" echo "If $PKG_CONFIG_NAME is already installed, check that 'pkg-config' is in your" echo "PATH and PKG_CONFIG_PATH contains a $PKG_CONFIG_NAME.pc file. If pkg-config" echo "is unavailable you can set INCLUDE_DIR and LIB_DIR manually via:" echo "R CMD INSTALL --configure-vars='INCLUDE_DIR=... LIB_DIR=...'" echo "--------------------------------------------------------------------" exit 1; fi # Write to Makevars sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" src/Makevars.in > src/Makevars # Success exit 0