xml2/0000755000176200001440000000000014151433702011134 5ustar liggesusersxml2/NAMESPACE0000644000176200001440000001374713746277167012413 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/LICENSE0000644000176200001440000000005214147164673012153 0ustar liggesusersYEAR: 2020 COPYRIGHT HOLDER: xml2 authors 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.md0000644000176200001440000000400014151211545012404 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) [![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](https://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/0000755000176200001440000000000014147164673011724 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.Rd0000644000176200001440000000450713770665414014671 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.Rd0000644000176200001440000000101013654264603014321 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.Rd0000644000176200001440000001033314147164673014643 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_all.xml_nodeset} \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), ...) \method{xml_find_all}{xml_nodeset}(x, xpath, ns = xml_ns(x), flatten = TRUE, ...) 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 an 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()}}.} \item{...}{Further arguments passed to or from other methods.} \item{flatten}{A logical indicating whether to return a single, flattened nodeset or a list of nodesets.} } \value{ \code{xml_find_all} returns a nodeset if applied to a node, and a nodeset or a list of nodesets if applied to a nodeset. If there are no matches, the nodeset(s) will be empty. Within each nodeset, 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") # By default, if you apply xml_find_all to a nodeset, it finds all matches, # de-duplicates them, and returns as a single nodeset. This means you # never know how many results you'll get xml_find_all(para, ".//b") # If you set flatten to FALSE, though, xml_find_all will return a list of # nodesets, where each nodeset contains the matches for the corresponding # node in the original nodeset. xml_find_all(para, ".//b", flatten = FALSE) # 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�13654264603�014713� 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�13654264603�014176� 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�00000003361�14151433702�012645� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Package: xml2 Title: Parse XML Version: 1.3.3 Authors@R: c(person(given = "Hadley", family = "Wickham", role = c("aut", "cre"), email = "hadley@rstudio.com"), person(given = "Jim", family = "Hester", role = "aut"), 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: MIT + file LICENSE 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.1 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: 2021-11-29 17:55:43 UTC; jhester Author: Hadley Wickham [aut, cre], Jim Hester [aut], Jeroen Ooms [aut], RStudio [cph], R Foundation [ctb] (Copy of R-project homepage cached as example) Maintainer: Hadley Wickham <hadley@rstudio.com> Repository: CRAN Date/Publication: 2021-11-30 14:40:02 UTC �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/build/�����������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�14151212034�012224� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/build/vignette.rds�����������������������������������������������������������������������������0000644�0001762�0000144�00000000316�14151212034�014563� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������b```b`adb`b2 �1# 'X&/藟]%9h Pm�:I, Q,LHYsSь`wI-HK î?"5lP5,n90{C2K�7(1 棸(\^P4�@btr$$ �Vs��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/build/xml2.pdf���������������������������������������������������������������������������������0000644�0001762�0000144�00000456225�14151212033�013616� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%PDF-1.5 % 128 0 obj << /Length 981 /Filter /FlateDecode >> stream xڝVr6}WԂ�qdd9LIi8E$.et"Bb/g[? ߋZ y!+! \ʬv9 cUIq>oE}v1hl<O_i_:h|/0%JVSJ!J7Bwpz(! avE﯍f  L"# mE&nHL5嵭P{9cu_Nt } [|˜L?(\/E/YE!$r�\om% {mQJ߻lCeCnXQj7/y\bN.RV 6&izf=J.W7$*m n=F_"z {fT�!p|i Ԝk,#zl>*(mS�_a \ NkmfK >_eUv*qL78굋°anu9D<GTLnNoLmL3՝�ʂ CR$< 'UkUTbqzs^%|5oI D>O}UN5E^3)j?!EA4 ^~brUM)0+wwJ%=ʺ3\(FJ# $hl{7kjDIȽ;74�F.2'na Vk_[paGcЇD7ތN[dLAyWHS/R\4DV )^6eatd$ڷZw[ =bZ|0_ $na~٫7Y t)ɬI[Y8-!0 Pkf}"ʢ&4Zgzټ\AF1 z=%js? endstream endobj 168 0 obj << /Length 797 /Filter /FlateDecode >> stream xMs :Z=vɴnjoIC%hF5nRd%v֤ɡ\,˳,+XEɷ%W%eR,&!HH2 $Y͜..3Au3\L}I(r:u[} Gr]lV1|q= HB qtthZix` %Z*tVڶܝwz<tWz<doMa6)sߘMW6*sv}2jE,@Łb%P2gR!#9֪_UoR p&['yҹ,R4l  ? 4)"@3:%|~kU:)J^;8}kzcEۅ}PH\`[M2eCH<N<-}ȑ%O^Hھ$9౏]{y 2q z㿫M }-՘=`D gȧ (j&.kw=\Fz�7gl7YF<1!Yzcx FV˙Ũ2w.p!{@iN*Ñ(�>!?R(Sdž3RDAJ&5gQL_ ϛ¯ WW/MW cw5M\ q0Bώ dK3|(tElW)î0˧Zr<?4]?,f? endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 809 /Length 1751 /Filter /FlateDecode >> stream xڽߏ6W1y(oib.fjmÒ/{w$yjwi Mk~83&& /$H>d( ^PQh&.F)xa%aR@~#CcLx>#ZH&<Z/&CN cΈi4HЍ"(^NDœދ>)`-֤"Ai%Ix "k0D8H'�{i2�JgguMBA y?gK34O p&S./Pc\TN-Qk<YVEtdGz0I#! :KEy7/16`:|#ZX?̎y�'E<ck6k { lK�lL Ůg?p<!7*!rFE R z6O9ְmldy紀|$U\](}؉'Zy}ldi;I_pK^T]Vǻz;SG/7Χ-w_ͮZ?M䣡cEecW!g8\j?Wy}uhzi/ gK5Cݾy= ~VypP&s +UWʹzM>۹(fIwU2z]rTm;s]y\kwUtzmlzˢ J'7@}5wڶM6Gmvˢҡ7jQWmæj6+?/wj \}Zw8ᑕ<XW:U oȘu?V>FGc>raĵ(nxuU/ߪuQvH5DEy]aU}YыZ7{QqəhItSavjgbfh}"ú>S]#P0Ԫ8i<W$Qp9$-pD2%q88寛囫~ͪo_ʲck6| #IOd&iד}tO|ȗ=_|($`#I0Bf-WnXiD=/ *1in ;_?-r\xkJܜfVhv5}[Q~11O72Æ*~hئjlilؚ77ўўўўўўўўўy9}r>?)//JFqd}9{DS0](Q`y K&~sԾ0 NFp=g1h K3 0MFFFAH�-AI_ $amƝ RHO@X~c -@I xy0r2Nr *`GZI3^10BL`"##x+M3J$M9<S C_xh€ڹ_Ak :f *d& 1,Jkԩ|kxYXL:A'%0_ڣLq1,Nkqr zyiFlaZk/U0 3J95" JqĠ.9jVxfk1,V& !UeP&=aNc35Ȣ2Z?: endstream endobj 208 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 231 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 246 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 261 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 272 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 284 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 297 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 195 0 obj << /Type /ObjStm /N 100 /First 878 /Length 1831 /Filter /FlateDecode >> stream xY]O[G}e~"$J$R[*`6J{6lҪ{;;;sfvMg(P&.bD# L mQb2E)В!Sbl H� RБ�1 %ARꐥgQ.3 lEaV '"yL{,xI 7'uqJ@F'(!ޡ>zg֕ OF"VƘ 1@Ǭq#l$C,Wr+ c9Rlz'd^+:+(glG`b1B=P΂䄩 }0vcE;JƦCRTCG VL&&p)pbn&py V.Ġ6�>UƋ鈠S:Rt:(<:]ݹ-}$@[t#b@BR{9эo&):W^]`GgLR`)Xr4:zMh!goOsk}5i^ͭx Rn y?4\I�/_ 4gì{`6 fmdCNדH?JPٓ_O!BYb'xԲh-mhiem+ ˿/^z2=L[MqsysD탮FAlX[j[G[pD)4?M>L ~>#;T+w Bz0$LƱT?ڃvoJ!TzRJ=YUlP:lVNFY;FR&ւ(GHaXk19?GtG+.@>Jq:<y)˕ vV蠞i5 +ұBb#]k -okv"4A acg: eiXn`W-Q3QxbeR)9P:YXd3g~Z !�HIeН2�4ι4.$熀hڗjFwLG<up`^PPϡnJVlϘ'Y|:|zW~ثb<8l;L(!K-رTx4R3VR2:TQcY;,YK@?|C8ۨ p g$7 uE#҇\^"y ՁVr& ȤJ0TÝET>8j?"%mӲǏ x7G%HSqS<7&[.Inٸ).jj)fĸp*Em\z*e[aMT >XyI,^tWro~;'xN^.N_}j>?a4\k$uFq%pia;_+9{x%P)dWXADa$ak:ӝ}dyv[kB cV0SVknZn417bKof>ջ:; gb*]^8ԁZ6xFeg'gg'Q[O! K+Օ(;~ױ&M�.?!\lJ,j uJYuR.kJDW /کueIRgiӝF0!%t΁^Eqөp#a Wi:0 TiTM endstream endobj 314 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 329 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 346 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 352 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 374 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 384 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 402 0 obj << /Length 1810 /Filter /FlateDecode >> stream xڵko6 DH@8[֪Xɒ+qwǣQdP$=cK2~c,gD [=0<kbڀp(uvŲDY#KKvl(M#gzɪGy9=�(>xӵI'YY˵Pb^ uvpbz}s:~>D'$ѫt̢KTyit:{Y{Vuy:v;YQ.ѻ%*u5@OS?7X?&=>T.3^IZy]kQhR "<eB�kHi\ qv>֞O=ԁuֺۙ3M=Gf/gf= T'1�ыS㔂.tԲ5`0OYJ+"mΘ8KVZZO g>:"oP0g}כMfۈ2x3t}j 0; B]wlgџ*-|9p] TNE:X3\G+XƊӉ㎁lb EuC]U\m w+z9 9.'?U0cGDV2`^.RG96Wa%lkO8Z6K7XMWTɏu)mdc|ɸ|Qt^[B0jqꢫԴyMHGDmb3%c<*�5J1=\b =UxӵnF=_4U E:[II0x+Y֩Mr!ژQe軀Sp)כ}X6-/M}3tT9O>wcW`)W:R}W� /HzPoZw<)>tC5tBCL޴کi C=2Dh*^/&u7 g]9]sD~8B c�$l  l]_֫"Y\UmӁbo6k[v߲:ݻOiu-f/̿{1<_2o C%K,KU^hkJym?*דAthg{Q%PjUK.Nyy|ᰥ(wQ;<@k]u*{:y]'ʯ0-Ӊpdb4eFPqael +&cQ.ƒ}vl[łzmADhEDES <Ru6sIljCط-e"aŋ 2ꊐ5Hʤ94mfq9̞7-,Ojz0)r4Xaχ*l 9휇 &!ڱ F9 s?pSG;g;,^pvjVQUNa(Ϯ􀇓^S}S㺲 a0Q0[?U^o+KLC#]fn8Ӣfki52/JJm%_�i 592`k?Q'={s"p%^C۝o~W-ܫ0hܿnKu Q605A,\ zxjƧ4-;`[hP<IwBTg)m=&: {#*f+]pDjNP$VHִ{iY4-6V] endstream endobj 310 0 obj << /Type /ObjStm /N 100 /First 876 /Length 1525 /Filter /FlateDecode >> stream xY]o[7 }aERRHe+aE<s"vIVNII)TUq,.Qq-@C.WfW)WͫɖW3] d @Hsu1%H[%.2e,`QE `l%V1Ȍ$h�.!dH j*N%�89bG(6PG\`�\1,1V {lL.fXHg{pac^{~( VR XO`(lHbH(,dN)d0,XTD\:1UD3"~l{*)l26+9Q ,#r.L oZdc1( #"`.CYT'j+jVPB$[( acRQ&BQi^48TS9BuUsg3Asڠ{v*ܖ~O@[xhwyޜgnmufc_iQ#p6#>a uO&Ùq뗛{34sq{nbҖtrz?''2<8{1vL#/uN! 8Tb+Abrr0<YU `ה.<DR=p 3'OhWKgGq>OgϺh:y?xԍށp?98Fýħn#xlW9d`xkQsu)*bC8t'0Nytp>Ԋ&0gcRoåє)%+ki]Ƃ)(4G"s+�kQ`.՗J M"m`n 5z+.=K>_(ws)伔đJ8Ю [fJzom8y3qpȓcjNG~<}nKBY</=ZFk}D[|]:؛b%\%&vhSi:]5K{J^^B}vVO*rϪЅNaaujnEbKc׵rK6:iUC"86,#e56b@+8]BzVs?*JUyTe8NH"3t|29WL6*BY. HH7ej'*iXN`N>|+pߖPʃ�b_/vHD|kgg_G퓷OyY"2A^n&xh4%ϹWz|0r6lЇ |F}QX7e] XpGt_Yehvőh(F<JM@S(+u*&~;j͏_ˏ7Eq]^G endstream endobj 418 0 obj << /Length 1551 /Filter /FlateDecode >> stream xڥWK6p7Z&Q@fEbi[,"]w!d&cf8oC2O䗛67 ,eEnB q qCߛlc>$y>{rDjr+bZC;33/Vkt9I^g+JL6EVɺ*ND}NL0k3E w0\NRl/║<vcףG)j?]!ڠPl[!tG~*fp(qʊSĸcd}"!G)G#KyFcNs'0IzICDKm"[g aJ5�|"f?b%KFBeȓZr:K"'\ڲٶGE`\JvY%b%d4ӑ=.P 25QqUd N F5:(S䯕 ˨Pq^˲V8 3$;idL';|zҒ䒣yȾD! PAA+ i h@Sh@0 "zEӜ܅G=fBdžNnZ3<B*dengmӢ@JZ^&9_>x#\qz̿ o,hY݈~b&)Rp`@c'=$UJV& rW�'X0tA,Jl) suS|?҅ҶZBLl]G1 bISJYaKaY1Sg>,1ւ1VT QO<7hu\QW'bR)NgS!jm^.zR:!\Ap[&@e21fz{NPG��(h �!j �>P߮vWI׫yw6o{t!ad=ߡ[wB -_ȃyr .`vPp|ҸW]�F|l2 rYVS(Fę2+D0S%9S.9cg(=!}\O5y@9dԐ{~lh@>s8ꉃٷFվg|{Zk.qsU?gYB&ռ\uU8JnPs٘smؕpC ۩jjXU_'^8C|g -JS2v; )}P&wg%yUGu9ls %[|Y}f&)ZXL9>sVhI7h= =7o nYx CD:y"6o%`F$|뺱~7t*3>;44B&Y!*A1WCA%/R΅K }V$^Qѳי)i$s;U8,-SCGQI\b/^\EKv竹pDZb^/8hSmn]Z endstream endobj 430 0 obj << /Length 1357 /Filter /FlateDecode >> stream xڥWmo6_!d&MR^@C öl_ڢ% K$'v~x$%j}{_'??NfIPy\9c1:%owDQ4m[lQ߉%K�3x<cWzm7Bo*oE}#-͎joKH$=:}?j˞�/D֫Vz]UD:Ln0JXb9ō27¶|˵XY҈6t.ڜ266bE6 ^kңᑰE!5ň%jh̓͟ril*Vۻ!zrkEP.)4d,%Ѽ|OpS3# }kYtQ'Z7*/ϼPs0 ~f̻-~ʊdu&o'_&P!=$ALt; ;QjF~;ϊt("*'zUH#2@i"0lQp2 -쮕WP SjW^UQ@t! IpB% X`e~3h:ߵyUZ.\9 Q߿oN! X^ePbdb0ΟΟ.v l-<mE 4B, hxFg7Z~-ojU6|%*J(77:}orʄVHd40phrlnUbӐ`GB!ۧ)aH[eau>}R~=#੆ ;׍1guNh̔(vm:=R5ݕ_OPz>4|@B DO >Խ./24zwKWl]y[ٗ=/rrZ3.8G̥,@ L79}B;xL}X�!rS&Qfʢ)_Or1Jsع$D2j,9، d)\V+1jTlI*@p+P,Ka?_NabQ̴& |q++HH ޶uR9HAdZ}jHF(Ĕ*҈7043TS*ˉ|]V>>oCj {{i_ 7GP=\U%EI`{ߧnRC۷$iA'܁A�xo %׍ hy%FawPkՉn)c.=c 6Ҧkn.zA?|OFk9G{YPt?.E9&/Z xcLgޭr,D% endstream endobj 440 0 obj << /Length 1607 /Filter /FlateDecode >> stream xڵXmF_RXR?\\(QƩ*%Q1i18s3&5IJ;<,8ybvuNLbɥX;R"|鄒@pgr޻_vŧ2=|ZUivqF )#aG,F5[X> Îpp.t7{:+X|R9%s|J}y;wT+3'!~4teF&#="t��b>ӯieqy}Z(V2g*CR1])Aگ&}W#*cX#c cuDOqֈa3ݪDt N^@KFV*G^@S1iN6Xg,�8yٴYL;6—ďEBtB0V0SC1DiLKc|n ;1(/*8'ԡ_Ã)qI"ǻ&d @z G #3=ʴZf,nqEO{H^Ab{(4KMn˞Y%Bj7%/Y ndj#e紶 O_Cy_YB(CnQrQw"\ :5ΰ#JH-fT p[f!FdqcBB&u(x=FJ?1i:x?=UFh~Q9z yL9bH"Ycפ6>KleVLe$*.5`c>�Lmvо-նWE9A4]�{D*  Fc:c{2 JMV?fK<�!wd!husSrU5kIj59d,!'W~ay C7_뵮w Қ*=T'Vra:l3AM "T3۩#zR&8oŖٺÄjl_$b'ۭ: 72\~bb_lK n7!/ }_d4UOtMOtti/ҮG򑵁˓�}m lI(SM &MD2(4NB"fSl[atRۉECg 4$%4_#&Gp6 "&^y 4z ?tuEɖ=_Yjr D)8�7?޼6aqH|4e4v7f* d 3 3TNsG: "%mU j83psS+jȔ`sTu}]DsS 4lpQ4:Jw<үڽcp~J8:jtŞ+ 9c'q%[`rݲU|ЍA�m{Q_M!?6|Mh:c( ǯӤ4AFgu[]91:=6V%UuWN>-Xԋ(<8KY endstream endobj 453 0 obj << /Length 1063 /Filter /FlateDecode >> stream xڥWKo6WCm I 붇`$VWcg}JsDrLE_f?gǵ"ܷ[QJ׷:>/8]~Y\=CNNjH@#lSԛ҃Qm 81y6QZ!6P -E7=S*Ah% KXf(]B:|Z2sY4Uǧ֑` 1|]$eܚϢL&e Z6ddlhQ�wWurɼ9N 9]D,q|[ 2%'3J~RG";jI28TBv![e1yzزn;lJ\+yGr"j@kcqR {kT:^T"nNޓyJfD]gfI1 0:G=w#odU-Y7@yƏT&pҦɴ`-.ǩC8wM>E~d;?ۣAHmٸVR$BI{?p^Hx *澭st <X.j$eoj-KQ|ãJE;RR( ڗ]ьб]↮1B6uo ɴw{Y %YI$EG@ubek}ͅ`Xнkw6ˮ,<zOXc<4~I۲EoA^.]zF kPf ;|Z8(bxPwV*}$HlEܤearkg3_"KL]r!j>V�!4Vt�LߦEY{a\u53b[%iؔ7<�D솉Nna=:c N-Oe _!X NZ5\xW5cf}6w ጿ9zz_ŗenݤv0Kw3safWWP͕?:f�d+�5Q�Rn<8AJ# A endstream endobj 462 0 obj << /Length 851 /Filter /FlateDecode >> stream xVKo0 Wa Ȳ,Qt:lÀm.mplvt~#&mR촋EI$ŏ>s۟˹ԎPߞlcQ|GIb lZf1|v>. Bp+U,l܃ 6.WK7uǺ?:פ͕0 "j3QMWax:\O"F,ݒj )#ȧL2ϣ O7PT#rJd qmhHErVZ4Zt4jdVkt‘¢i (.Kb$ꂸTGc!"R4?E>A7R=2 } gPEyEDK)q:{4 D*k$KQ<utIpx)! <SU>g`q%yb iܰjS*uSeSp?+-<g�:ܗ6Dd`TE`qbdc7[؄T6un}=PItkS611$@7M@e߆fHa\Bɇq{ _7μ(B~hꃨc&-84YPc͸lia!r-SK/39bLJș?(V^MJqɛx^θ9V*u-a,c<fo3nDvGvgQ8->MuK?l%^S&x++S}qu'xG،eúXwJA!m"Yc-�E endstream endobj 473 0 obj << /Length 1442 /Filter /FlateDecode >> stream xڝˎ6XsI}!mvM&zHTh[,^}z@v=r4΋󢩳u$!a($̜/.oO~ 9(}"] I<ZrόHqg1X/ߨ{I1i7^ ( } ]ryuS\zEқyوQqH(EJBUuk_Ig[VhvN D&z|'uڼ*4tp,8'<\f&_`WPc2B=۴̐děDpYwy]a0k c#2 En[! 5lh{'oN"ST ,I1�I`hT+kb$HpTb >b u%ړ {8jBVǺܧLO0H+- cNW1g7 1:n#nJcy$Fj_=_SUgk;aʅ0* 6=@A]x!:>7VL)ٻ%)%iqpY~he?vBdOZK74JlZI).TW!m%7 �I+w\T .jM-<c/Gipokق=(\ K#/: 2涬ajdZɽ钪 AXhPqh]C_O'Y.Ke"^v)17m:_9u*2{9j x*AD̒"7ޱҀV6M-MqmܾG&RTڼM P:Aq.q{؝(1Q.&F<v\,Aȶ6/<⅁v7H7S͆%VryD݆ L( w-^G%@(ԅ,?Pٸ!ysN/?jpꫴ!zjx?nc.cLS<"~zF1īTQ7N|''5H9mG6*YbR^7-bI>k h⍝a׉Y&r] OӁߠ2cr1, I%WUAj5Xh5l ~&<(DmLX,!QF< +j?0q||q�@iT\,8gnjb(2oU+V=Wǩz.Cyq *|*X�EZUH{uÉ]1Z%֭zے9%*#%}Nո86ؽ)izEMAa3_i Gpk.ߓzcODEs<Ye86-D 5iЦhV3б=B<~3'8s~Җ_KI endstream endobj 487 0 obj << /Length 1056 /Filter /FlateDecode >> stream xڽWmFίX% e߽R"EJMHU]X+c K}޵!4`wyyfv hzab+l(! "E ͖nI '&MÏVHb%x)#׳ޟ= #<SGVC%Agm(JP C0$f8ִIp${}{.Y_mVNU̱kܯ#UJQ,O+[,dW8yt6hDc̕.ޞX8*b0ki׹aJk;lF$q=$i?`A'#! iꚣ_psSֈД4}Q1V0H_6>9(0mVJ}YtXh28vgk-a5_߽;bNv#VReV#J"Dӕ/ؘyu'bM4p{㚐6kрx؁-bY <o<w(PT1,#)8 {ų:|RÂy:^.IW n3Ea [/4P6IϭYCidM.:8& /Ø LzooDuWa }%e LLmQtQ-**S/Q#BVWTmqH}Jg5#bfC}X/Kcr%Qa (~bYBѲ*#X+RaO)P _OW5 *Qcq&zaKXׯ'#lYbJuH6O')e|2^L' Qdl^F<4WI7ie棿a sSRbG �nQpv>fL`ɂj-vfu3> 1:@v09X]fb &$w3̬qq"涞|6bn,n v̶ޮ: d [@fn}!%q]Hܮ^Cl]ƭ�AZ endstream endobj 414 0 obj << /Type /ObjStm /N 100 /First 870 /Length 1538 /Filter /FlateDecode >> stream xXaO7_ai_U*mRLچ!ѤJ=gK!´I@}~|>;KA\_PWubbD}"dXϦabiVW+"l}vMP4$IJOCI+RIB=N1R\$*PSmehE] L l.&($`dŤh$`TbIXco5j;8%4L1\dS6zh@^`F5HulA,b[Sb$PHL\P&⬐aj0$5U(q 퐀퐰xsb%v:C.l1Y |(0J2�6Maj pv&J:+ohI_M94d.zR[(Y#bR KAԆNXp ٌ#&P[a*;m5]p2jߤx4t /c d_ٛѳgfF 'foGM5ͻʍnEŴdR.HXKl^ª"("Zʇ׋tVj݃?N10y? /`tZ"RM {|q4]D?NO'ܡ-!U|D!R`*2.5fsh<lLr oW|8. jxqHc6a3D#J>' iwwa<{7>3?[r8ܴvfHWgVk;'d绎|sJ^6&.hL)m4Y뜻fks444K⛷I;l> CǸ</Du=̖{ o>mat'=X~2 #רtue˭;0ױWI1%c%x 3W>0W>Y$ Fn,w}3OyNNJk/2=o8(8Tk/))W.`t-$0Nai?9Y>~3 Շ-d_OgG{o¯ yq2Y|{)|zK:(|+lVoIRǭ7o3oJF&lW3rf:]5G�ۋz͠l໿nl! HBBIBku#*KU/ NRnL�&ܑuN ix tm+$'EZSy 0D1>p)N09"ff=mz 1?4!;$ļ)!RErE|DM`C愢p' +m%ߠobsƈ%2\kԐn-ҏٴ=Է{AXڏ>Pu/؎}|-R :7<@jJX3Y;M(~Sm +xtZP7^}?�nG endstream endobj 504 0 obj << /Length 1392 /Filter /FlateDecode >> stream xڭW[o6~2 h],@5]vZw"ѶV*I "rY EwGckmalqI'\Yƈ2 |8%2lœ7Kv(I@/kImac,Ѓsn%\_4e׎Kr AF?t:Qq vYL(>[7b=r#m'|˜믮}G&~w>=q#⑯uDĎqPOto6w)/3YzA`+)fW кS<<>~Խ<ývs<:M�|Tw>^C,U+=ƥ7]/JD] �a9@' t�6i˪w~A`gh o GZ.6ն3[Y[.+׃;a߾mRZ-G_^V2h"uPj^AXLZ'Buގ&[oB.[m& @R@TIvz5k �PƎ\WYY+RD*/%<%Ш#h?ʲP^lBK#Nɤ>8ʣ޺$CoOWL<nPuMvheLT3}lxNjݟ9.s\z fkAMn}UG()_122CX7~s|v绷㾷(pͤq u Mt pAd7mŪM F%d_^QCլ~̺r avRHoum0M򛸉NU(8Ya f}EɅYس_&1-AQ/ kXv*V9B2lDFݔv}(T`jMjIGrn�rr?mQe.Zc�s1a4qQ|mV~y<C!Stҙb x"P{p) yV%VѓHMzyIP _=z R_{<6;yzFP xMjQG^ + ~y5TB=r(װ*<YS9FroM#ZLRok;Q ”qߥq+H 9A"wO#y#=}\XAϿ|8mŢ7O??ymX9?tQ-l" ׇ:FiJ['cCz';hMd\( 0pDlj}<~Lz8 endstream endobj 516 0 obj << /Length 1008 /Filter /FlateDecode >> stream xڽWݏ6pCA8cCP*[ԗv\O@ D M-wl'!S'xf~s herd?qE `s C}K)TLNpBĀRb9{DA$3)h}DP/#xU`; 'y{crӆ@ v9E ߜd8i dq*s9\S 2r(|1r T 3556)+\,y|(,;G#vBBܠNH.cSˡ$4z *ar]B8<]ĭM*Qv\%ǻ�==evB==Pv.&,W SʢDYU;.Kā^ж>VrhmiANSK<Y{^Xp�z,~k+dy\4[VU[9}a&-tLZwsּ\pHk<KGQncEK)jH4|Uyy�u3�l&cLJEH�ksk$RR"(N!L}'vqײRʦنlQ׸)BRj\upvo9 *Q^S$lֽmp/댧HX4dpHd1g|05-SDrhT5aŅySE�h:*ZV,٫>mR{>-j+=J wq2mu({C3E)֩}x7qIfm:Ԣjz3e ~Rlt+J8Sj֭ȫ#oI(BSCKרW л Lr>;d" ;3ښ9g~hH S+> Jj/}ahip?a`1o-c9O<sO\Y6 e[�1 endstream endobj 531 0 obj << /Length 767 /Filter /FlateDecode >> stream xڽUmo0ί avRMZNBi0)$]@hJ}>?Ͻ"SqVs?G̅\`gheNoĮ%~OY\vHPP [όWUg<!h*bWpcuo_V߅O vE.q0/,n`I8Ȱes DLnJҹI:=*&?%?0ܢ,)4iprmC}0h`뗎)u<XVD6DhHr9%z"?ʦJׁgխ4۩JuJq}uzRڰKBþfSs<MzP]9OFhl>`9# чvTRA#4)nك=&T.X ;<[|`W{Eب*X5rusd7t% 8(r֡nbYP@Vle{<xUmjN.>e0s0߱Kv}SkQ B(+i(,,$kNPINq!jXgIn6#$tHM˨&ԀðܚD4 VIZ~J+ 0(8]<`Smnކp6a;ڝmȮ%XYJO=FÏ~<L?o2 endstream endobj 544 0 obj << /Length 629 /Filter /FlateDecode >> stream xڥT]o0}WX HևLK&UVZMꪊ0 & iuO{5AsDgcd8SQCf]./\ݚ|yg,kiEb?7W ҥDo” 8(ɍ;R8@pO{1GBH|hcK}`)y{$zvGrcQJwmK=QE=s! x/D[B{D!>IT٪bgk M,gyLrYdN1֥ l'b7(H ZsyS:Ct ٜYGP`F(ʢĜՋ^As`>hReQ~+A`SuN Y1z!u57V Yדa'8_-:|4N lQ+qr8ϒTI;~Vq'(  _ָjպ ^.:[{h&zT,[M1$v* O1\u_M3s=�: FO(� _ o7 endstream endobj 630 0 obj << /Length 1541 /Filter /FlateDecode >> stream x[Ko6WF|RS(r- blHrߑD;EI F@|!i8=gJv캈2GEO|韇?;>c(Wr["s]Zi- K5deNebg-(ubF 4 +ǿ8_o w?a'-vAğ&..8Y$ Y/4oaJ4 bw˼)XwZ Ӑ X/&}o.w/g1 (&@>ǺfٮH0(C�fz,42RfBu8˓~s0}OϓmFѴ ABLMрB%M02-_ ?a(ћQQ{!e%M[* w/8'fF纾p3{gxmKXyO Ž~V78(>9R|5�Bx-Ƽ ď)Evy!a.iŧ(Ҡ*A#T/]H:i'>z1+[=4+((O'..hq܊^@2_b|u_r;Fa~z B;YnW6pzԅ8:a V ǡr^\OL :-C̉Y1P'\G3.n/H A3 rR]N)/-_S8G-UQM,IN1UO>Y/eWd"Vc9 h5?{z #|s8&:re_Sk_ߚ`#O$}7vmۧm?`j? 4 >7Aǥ<W9AeS氆fcwc' �sLV5='V22ƣSAFj^Qs9j!LOB;/ sg%/x㣋Fx? :љ0bkZI4iʲ @M . CmMҬYX/-^GaZ)tT =U5jjP@1h25 :qP7N_Vh}uS{Ec(?&ZA+kytGV|9{V:~h&V7+kmn-tr޼q>yaoZ!(litZ<K|ZyP8y MFfSč~Drkmju{jiʷ5j`}S75:Y]Y2+磮ݵ'TVYB{Bo\s ʗG+Ij_a3<Jky+jrٲ="Re<:kqo=qb�> }tXYOFg)%ϾHb,˳G=z :,s}wMQqL}z "wSG* n{C endstream endobj 499 0 obj << /Type /ObjStm /N 100 /First 880 /Length 2141 /Filter /FlateDecode >> stream xZKϯ1p$  I$ yl^Ý}X;hK 2T?ֻحӔZjSISS9 -K*Z6ⶦ*wK(h KD F*fJ"!`!)Xj"ŏcD123x5f5fDq\1_&:qM<9 0bؠ(.jXbq\ᆿ1 w ,<l `.q.@`/idR$@PlGqQ�4.*.<fZ3Q0áPhKH 6fTBj1a"+ aڬpSwS:�n'dS b%h"B|�wجPZhc02> A {[-@4%4lFTJnjJu TJjlJpW FYc#X<%VF 0ЌAUMaؼx~.۽J_0) aAZ˷:O':x/j Kg&\,|?<n`{T׻t?|2m~Nuxnv돰fjps~{|9.b kJXX|'z?EI)BRtͿ>l9\+MouIrXL Vrq&e}ݥ:m?9$(O~8BZ "Q"̰,&πPD?MklJ`XEE!"V9"sY3Z G, ?"fpFyʗCǾO;vLG|P=Q 6'dȘr,EēgUZ2Zbj1KJY2} >%1U &/̨)3A@H?0n.||w?CyS!剽 EGHK>3Je<b>e1}b5ID%<bC,3&0X{"椻Y^V0(S_QO2X6KT)ZE&$zD&2=6?/ vFQƨc1q(烟~>烟~>7zAb8~e+_W2~u_7zhW6 ~mk_6#?Fӏ+Fc,cc9 ~4G(|-N ~4ǃ~<ǃ 3N&lzHM>Yt d˵ʷ `" t|eRH[' wAgbq1ȂPM6!"P<Ыi "Ǚ6>%�"zCAc:L3KȁjjO#%!` T2�=85}CP?aJuLVI[ Pլәdt`Ԥ$V`@hjZ<:fBB ]5D l` S}{@WR ` \JQҡ xI-Gm1hHÚ=,�uLTeа8hF<FۙU2w~E1K OȲQ]m5NJ9Fne*cSe.V* ۥwxit73bOƋf; [>]]{c +R+ ܿ8B@mױF`(瑷qT#>#GelU>ap? Y>aQP.aj9I9>_H.єZgtTë`3! QQ%WZEQIx@5Cھs~ A \dx9[, A4m[Ļ `_x.|F4-xYIGNN'*V}|Kܙ-Ʒw(q\f^!G|ً$EMq*Ν, X;5GA!O?4= endstream endobj 662 0 obj << /Length 664 /Filter /FlateDecode >> stream xXMo@+Je!j=T*%rM,(nl;^ 6 !,~ͼ��h2e h` ` eH ̖O}Li0CJ吞O폌P=Z;;ߕ<d�>PJ_T(巛P16;đ{�n*)GuVx$T+mbҵ-I59=g_jRHK<!˗1P( Icļ]2"DSB y9oB"}Pq 3~ o1m&"]DW}&G:P5!ix*f8s3:r-{,ɳ?!!AITxvXkZ }?�4p,PˤCUT_weǒ>dr:Y*}�2V+y^|yX?3ä+!Cˇ8+DCϠ}P1(7+`F3F~t%@\x`+qkv 3q�6h xm3n>h?-]{NXfAco(rAroφL?u[bc)n  *y �Ֆ940F]MlGn endstream endobj 675 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 677 0 obj << /Length1 1386 /Length2 6039 /Length3 0 /Length 6990 /Filter /FlateDecode >> stream xڍxTSۺ5Ҥ#H7 & wAjHB$t^7J](]zQA^x}kk͹d30T`($F$[� PT!4c$f04 T,PD�@�4HB�RQ�U C!ahN% �III(<0 8ܰ!`0H#K {{{ B('y^7 0a^0(�=hB$�g8/1 C!H(0Ðu�l�$W?ѿ#�p #�H/ Fa^`8n PW2 cBh8׌¿`Y UA4ɯT0v}+{GBt6Ex´T`&ۜ`PJ\\ =�| ¿ ~;31`pG 0@tsEp�s#Ik9ƞ`�0( 7 iݷ43(@PJ�@� 1@?X-# W}e?#^?s顰̅xMtk;_YWwGo?_v#| `UjPs_ՅAn€jPB:a-+Vp /e77 3@0( |XA\w4]0YW AAMDL��`|~ ,Da!�쌁�GɯؙhW98r�LV{[0 B2?Ȅ8Ub<Jd-zY0[cꁲ=~\yl�1W!U}¡oG`PӸUdC {+|+Tً_]vKm�%lLxmGl˘aKkjLO-KG38oV Y?,zX[#^Ip[H mrf4ةJyz;C[$"颁AQF'=4y֣f{rL ѷ8 >P欁gՈ" zX]tQeg: MqDmLПg'Dl* XG.d44Zxzl.˞#wN+-n"7Z^w D8N$Ytfom%7k2SiCu&'NwiW`O4(4zgGl)<MINB'r-r'$R֭0v6c_XV뾳}=$xvņTȾbO ;?N֏ ,#bҺVힾa?rb;}G)>ð {x1)QM�m�X㸅ȣc7RՙݵwۍF=UsRպ\RfAd'dPYcBA{hۊQK,Uw ^4mu gxš? D?|p{jn+Aݥң"ę7Ej:"v"7[Q$[>S 7;<Qdnef&NJ[DVҡ5r=gUw8(B�J3{9Πsuwo!!|_mTEQkWM%i݈{1:O;̴LVAOE;747LE?!һ$}MaR4͕zWd'~ 3C?~ՖSv[&-Nn䃼@jie5{左[F׽Ts UIȧFr):]JZY4%P!M?WșhϏ$ءaSzGQ4cQ˚]WV?X[t8 4"Se =y<#0lZp\7.E{:pU"U^hzzIǶH�aITX>oxYPb'yq)F~Oi7&lT?ˮge(l~90qV9]\|>\*Zdxv]W}[?+gM)e Pjo}q}G.A�j`{ƴ5=G3WC*IDzZ3+<pʊ-o6`0reNcBč O[%,qe9E^Y&DYug46AѓC.!1wՆO3dz8{Μo�wzB>W- u˳m7fHqw0LgJ+hR7RI�[<]6C3WILggdgltyͱJR%5j0[0r'm>8i(s>{meǏlp|in|;ԙvgn]I0S? !0j)n-R}E:/!#G㨛U9:o۴?5f>b?^\sNMܥb=!ڌ8wnc\6΂'2,Uϼr`}Ʀk^%]q[9NJ [x;N&"- 5z.6B<{5B޾K~'\}BЄeG4lz}]g$-!JXo*T2.?`gl`)V !d~oѣnW?wݑH ]@ O7}oz]y)1X R|[727r4UE]zaEi-U'U7yYhc-b0kx'8tx.Dѳkx%{@! f njuɁby蕋Iv|Ho J8 3$%ͽl˾&wIbpa[rfR cG(]S6!bs~P^Ξ}<ѐ&A$㰓[v²s�&>'+Su oR!Oωm") gK[A!ţըC~moC| [P輱:Rǯ.n"cd67wK6Ù_'Sp|,F|a.2))9 \++ĺ| ,"bBnUh<gY 9q\nn>ME3ƢQ/~;XT悔 MqwQ,;[П!%7QM9J0XHtvdK.8JpS\dYiہQļ J)N|[!=͚QbY%F~=Q?cґF՛^gl᦭*Ҫd_-Ei;·'Mc]L]ecgz z 6R kSHXܕj^TQ J̐e4>c V/cbje`rbqؙaΌ O`kn_EkV2BDKW i7Y͎rK%ȑ<Q�Tn{_=+V4]7O9kc-gGzK/'6ƲF=K znHH`ָ@x:gV_y"h;L㪀)xk\(uƛ[ƻG uɡrկn]7Y!D Mc$ƣ8?(ۏ ҩثǥ8Sy n鰃a1y[[3e}s<i[eB%{h W%-([AME_,3摍Y3\e| ,E �٥gϺX'wk+ M}vвY!Rlv] 'k%z9 {3qF_4P#D-)̫G\t@?`#>/ɷkhԵW{|Czn,)v_-vw<r3#&ϕՕv ->ı{ e yѼ5OR d;, ]k<zlK}RUJ7r-Uv?Lw>A\8]vn>&אY8Ca"r7q֚啢s;<5 Ll@.Or%Ռǣ==+䂓6sS/n2~ }URڈV0fo0pj22fm˨@.g^pdt,Pb쎆DY0g+*mռ?sngS~)nFXN`fLe鳨N}t2m `^uyu'cS]0 `%O)Ĕ J(RK0)a䫌  "MO-5Y@+횃-aF $O8fh1*N>niȩ.38Ep:Z=g\P_kn+:Xh߄oqʑxXv:#-"]SY 4{r#}1E(BuY0ՊcyOB4/rky8H»rCo 27n'EPf^X|;8Ԃ&Q`YKFY4@F3nfyXܤE)b /c=u1r5|!*x]m:1LJukgsC:!a\ ݅xVfO^z3z:G/NT+t kNQg7ʯ62OWNm7w|PlU((?=$F_d2R^_EU\UE"||wp_*IA؅ӊ)AĨq\ݱD?jTI?"+!r S ;/B،1ПKfv#{POlduk"'r OP5KֺAyY9XbiD*NQz)hrM�3Sv�{COEW=U#sSc/$.gK!Aj Cb%\cV 1B&m.T 2@"fUR_B>kqQy'E w؋,%t=/齗AA]ޣߑRFɓfab<Șp[Ci$q6qnyQ 7(%CYFXfr9bR3ȓPW@яPHVrJU͋7p,lk_*Oh}'yIk|N�-LKR}şua sjR8Ė8w_noUmNf S`{*js,W|ƩI)i"flvX=5S]j}1w,oPN5b* ]*"KzKM%)։u.MCI.LDb#P3pAk˪kSE]u.z_|>M`qX>u"9=zڳaz s}%p^5`,hoN~Jxd~;B jwgTFCVclSd,iRоTsIXa-s*:EG-t>ğJX"[ss=d_SK hǧ'y~{j2K` ÍexlTI&yʞZԁ~᪸ nUmV}BWQ9<N6%fY#=V[A@6Ym)DWsjDy}lҲ}8ÝӜkV9~)30P{P#{E$kߓk}_.'B ?c_WAض]<^: }ږ5N(̠3nϯlE�ov<yF;%߬Z?]Ҩ6h~coe䕎KwS?ֺL-kw_lŸ{6+(^>MD`Ͼqn /ο`i$TעKr3ݬk-=mxA] Hb`#b\ ^y)Dgw06|bNmP`f&2E%{ E{S0d3)Fy!Pש݆mO/O&h@*-.>͍$lmKPYg5PCk-Ǧ *\Z&_&FLX?o-X=8~8 .+"=`Yδߜ7W@Ce+37q㼮Tw;?Fz0| /|;ܘ:o) Ds =K-a鴨\gWE <o4'Au@ Uw[%R*:f aܱ@4H֥U#Ov5*?$ht*cҦ [O[M;/:׈/؊ ˍ+aFʍm85w8dSiMfT]!IX6Jx#DWGjoL6Sssf#S"  R{:DqYd_(0WT6TvAa#I5D1H_mʎAƇటk߁w鄍XDg]?K endstream endobj 679 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 681 0 obj << /Length1 1626 /Length2 13614 /Length3 0 /Length 14456 /Filter /FlateDecode >> stream xڭyctenPq*bضm۶wlb;ضm['|ӧǹ}{N>s>kIh MDlhh96Ύv6v42&O9 , '@ lb`d0ppp�fN�rE5 **I2Shaf |p1ژ:};*�M�&�!9y Y1� @ lhma02u4�9�q�[U#g,GhbdffdKE �8X8:~>,fN=pXY;Snj7 ݧͧ3 U^X8 hؙ~Z9Uߺ0Z' [G_ M�@kܟpv5jgu_uK@v[' 'GkSZXϜFN,la [S;�?\Ln_3C `lb K'k@?cW_\Ee l>;d l{ k8_.6/V3ZA;kI8|DzZ-E-L-֟[bkl`mak-0N/X25wT NTPVNNY;"cg ڹ<iX4L w+@ :89X>goaDl%'[IO_j#gOƯ.qYf9ՠa� +UumsV6Lq/%)FzЬɺM~xQ!mQM;S\Jz3[ ;�}HGB�D1JA@l�A?=#M8~| 쾆Ǧʎ!2@I:%Htrw7zxva:5%WheL+7(}3*iwnmdTt"mj4 ,ǦB<<F5:} =|agdi!a  )7QFZCW^λPN/+W# ! ˸Dڗ1&|CS9s8<ȯ6G Ss!)Fգ+ 9G _7rTY¸âOY-l&ߙUl|`,bҎ?,JS]࿋~2)g л-�0[ghC#'K5Cp4oeX\-Q:0Y,!'+;dt ʅ;am69@fZvpx5T9|A>;%G?i!Τ{j=1#<Pk9 j,E[*=gtN˞xn g=`{�}[e&7]N'\0WqraNn=BLI/WhH8FjlT=DiXJʡӇ>-.{? B75q [Pi1XEp/� jg!^\ׇѭU`G;ŭBb$9U|`Wwq|Zb#_^&6)IdfDJk^!oo[Fxa4Nk7{d(XG#~}e0kfDq[mdt�4Vn1%hTCȸ.e3GV}E߼uvnTL IFFX{ijYMW-_1m2rصn A2TqiMJ M;K)BPQ[8O.McdƤZ#[rvSK[0e+Oޒ~ K*skLRlՆIzkefpD"'E)ln'S ™хjb1\m*s+Z=on1ٝrnc=F.AH0ID;)+,9_4ɺ: :pY]*]r]-gxaod:unND K?B΍$)=eEid">P@O Cev/K/HgQ[uZ8c&}cķ䮕u,T,bC�r)z(lcEsNJpP#|s 1ږyy;VeNȑ␍]kO Ɲ_>:H.qds:jF Ńwٮ +)bSE'k: Ca)ž?/@Bv@wOGfWw>$OM"6_r=J>c6]Td>Dkq:*]>w9@O9Սȕˢ2$A"lcB))%I3PZլl4dhS 4]FY$6'xN5h:=Ju:n`eά^   .A钝E\Պ=LD-@Y^y3p4@8'y|j!PZ&5Y7XY_XamPI~9['Z&L ,#^i2V|d_�E|e j+'<:YIܩ3D\>E+3^/rsEYh]x ~ir|ZPelP -iNTB㛣a,nup9 s+>gJ{ d+PT 𵾑Bix7M;ѣ C QyEfxZHqt:DjxgwZvs 8X^KO1v)NEސ?zKi^.dE<U37,4(v60VNPfK' �8O/gnAs ~)cj9gEIm*W&X><B,7iUZVU*79o퐂r€.2/",YvrW9c-=/9\GܖfdLf 6 [ko;.h#8<]t_Vbp9eʯ>/d$dhbC}vS(|7&EElVO_hٸTUflF+NMUŜ;>w=<FG<9DVKJ?q[p\O]qGy<IR AC3˳wEW~(f:EXĐ_o|.^5 P3ueՒILRV^i~r:2X9/.Gr2úv/kq�8�D^ f~8W[~V4&(j__FX{ըeAKC�NqAij^K)i+3v&ت#N60~O8_hTd.iL,B:7b'[fJll6@`kȋVIO&ᩉډrjO"6`kt{8{}^%O Zڏ ⚱. 821[DʔcD^hڳ`Gez6b clzÒ'zQ7jOFQ/P<,nl0'-wauB9&wfF 9Ieg1C_{ }q3砑 :lo2nM$0ΣA%Y(�_  sBSp(`:vʵl [@/436Pq sTיE27|E<O.Rz!6f D/a)>I対o(V1'ȲYU8뒩 hWK^k+6lFZu8;&H^dx:Q+X&P?l)YCIlã-^H C_co*XvV`u^ roY15S?եnl*)i6H+rc.ē|qJߵTV֜G0 L*b bI2ŐQ608;%o!S(y(?D�-/K>l!he!|S6J +C;m Śʺl<!~eڮbA wOH/^մ B.(xw˞1)Ǒ -`t0v982Lpv~)Ua}:_[1Lx,yn N֡L=7)yXĬfШIDzÐ@Gdez_iDř?RjM!UZr{~\!-�k[oNhU.[n0`R"RpH4!0)IzI:sEb@i ]N/zےuk?pGk3PC 3{3`B$ekMƎ^|T+bXp<8p Χ"N4@!L^A~[ ̗7/ 8fɧt=UP dFU:!7c5˂ۋ0,oJB275ܺM@9w*Y!!w#gt [/<Q&y*ʵ#o^zˇ"4S^դi~Ub*| ђ[U I,^/3CMYyx hG_۩h:̩|M!`kUj5=<Խ `G|48(j@KQ]RmA?Zf9A(3cظ37vriDCC3J2!4ёҸH="Go͉DRlJphoя1{B_R ~ΙtXWx [Jukon.qx-{ t`$L#OTʢY;ӎߣik O]A`il̲VїfoY[(oQm*@,+x6'b=,ԳH|CJd6\@m1w&köYO&'g}"ꕪ "w1 % ͐/&NQHi2-kַ#Dϡg?𶇇Jxu磑JkhxL ;{Z&$Bb!zI+˴Az 3/C>)laӛi(M? c oL1Tn[uAf,D#K-NC[5|<~zIl Fv'N|&ӭ!>i).vRZc&/]-hz.X{?F0'F-'+A͘ rc4nbMR"I0=Rl ]P; Nè*|,6=f<a&}\yzB!h6<mŎ(\;;L"ۮ qgV]>㢈R1]EZL6Vd?1 a<2c^v6" t/ "mVeg{'>:<k ' ԸJLBX^gZΚglsqC`=zrc:~{Gz/ęۿ gy:Y؂"H삈aD=^t!r%~yāllD|ֱsf*p^94hTе.=/ **);$4e;\wɣPCݬYtG,2(2dL֠rA鱁P%yNI-p f'x ՚D]J ʦH5kF{mܣjmU*m*yda ?̒!DgQ2pN8Zj ͲG3`5/j[1ng:ONhWx95+eqg2/7ho/8㝏LQ&51$9$l+cG2Xk-jKK31<#739ksX8wؙ1;6FX/KDR hrin1>xNص].NuF9@BWKBUPvL z. 7ȭY\d_B '`qjAz}GhJ\|3ڝ~3({Zo`Z(v4.HsnW1ͪ={Pup7 sщYH)JWfn}]^HR=ߧLFم;YVȺF7 B `|=\V5 P+tB-rW!ТlӬ.&{z,|? !O<} 7*SNo@˂t-͊ \Z~#DijK_'{Fl4�|p[MSNV�9حARg]MSEe|aJn⍆#e6L9PI$?fՇY*IsBϚ k0 j﻽RN+w@Uh]+-_<d9thV˃9ӷ<4~ v9DNmMWJՎH"ر.2c gJz*;vvYlWM=bwmޛ ųIXF#']̙FЖ/>IݛOև=RbݴP, dH`v|ÏdMm6u�f e 77^VIK(˸$bTyJ5Xr#Fȕ/tC@6s9C-- @B8hO[2nf4NO=0.g̗o|ѷCHނ\&`jUWBG=r!@!.:%p0|V bD`7-#3{Ɩ$LMH.rLzO9ˑ2I# ;ZܑbmGfĂ:l9B]�1{sTccdX֦';?gl``-`8i;xa&=Wn?ˇflJv?+@.^*�UwyO,,;NB 9N(EZӪ6Z3ȡPS243vv8q苞 z2�kQ|HS r ]{u^Nj5 n0:Tj.gY9t|$7K\_Ew3 V;{dJ(A�H{z7+bﻗW)}5=tXGM("g}\#Wqj0Wd$&M|IX 8TK曆Rl�v㳨+Vl|qJU+^NY8d WZ+ÐnH C h eCmpAaar|K)# J{pD){ iMa}QD nM8ﺥ>g=4/Y"& CsyW_v~w*@>"s6?1Q*C7k]z$QQXG&%G _xYE /{p~8s歯W%ѪGoy:*aqiQ~#a'›$"9wx[mum}aZЯG&R/hC~ᗠ,Hx>r1YU-ߗZQchUSQXzϟ9iqGC{�UR+}c34lu@S>TՋ nLl½nv0/I\ z;•Ho }Hp_}LcUݟR3CFW,"h BGRȀ<fK.B #S}Zǝ!`Mܢ^L&É OGo+cRt9hl[a|}&+*b֬6(<6\;t=ƴpL+zZ+ګ_GQ~Ilކ Yz@He\rlSNwζxD .4VRN:0!H'w ޢ?l<sN[‚eQfK#iѼ*-իq> K5XLyaf =Q79H{8E"phhK$WgM=EIτ z%_QUU9Wqm&pi])H%16!�?R3e{7![!d~,BzOG/1n}�BoΆcP2Uv< ==ـnEJ3I#WxdߨfQGž(9+eÃ|G]UQU.^ȁ_p$ EɎsj1=IRS6xW*HoIz>U\8P.֒jM36eZ^t B%Sϰd\կP\>Xc|4+ xZa>: & {CrIxTW?yF9eL*'LW-Ng7dyvwĉF%[nfoE`n;3nիk'f]txu_z2RfU5auI4ӱXzcncQ]q=S8 rг7kl|!T'K*jI#-�%2<QSAא:E)troM(g TsGG20; N['>$f4&6>;OF^ϡ(a9svR<n Z Bplsd0G'%; @Ub"!:*B ßЀ[Zl練;s5dA>Y H+>~tIc:-*p)U` GQ\zB#X?(wB0K�[-o/{tMm2D+d)8R2'aWlݎC \I򪐛7zd•T[GaEsc m{W6yx"mtA12 yUdvT# R%1g."w_UeN2Xf@9#+?A L03zEmf8=Yah[ԧvjh4;3_ \#ϫ]B`q$2;8:QO^KW/ &og Dc!!r06EiTA=TN IH0�ZFa\ax̛Lg({Š[n Yu+TxmpLޱv #$b'X">\9\6>-;ѯDNSa+9kg,=oE T?:Aor lzӥl>o,r.hcuD"4I"4^wv}1&+{4<lUo?VU$:cDǩL8}҉М@ [5yd Vא[螔b %n17JdSdN=4!0&aB]P$}bWI ΉG'0w”VȬo*3W sanpɰFF1_ 1Ҩ6'է<dYiLNͲRfnŔ?"�G6gjv.;?U՛&VX3`n3C$1UE`;8<''WãYo`ZS#(#m}d_ Q.BRf;ڶ=X| t(,>뺓 Ź#l!%K p*KNPB a3hB UWDX@ ˟Y  *_!3߱/z, '0 xu|~*^QUZ9kv`, NCg< S*S~n-NɃqBz"1G5i?`o:JئC/GA�-cdUDyM>&Wͽp!`I^n9܀YX8R)~,Qzh^IXiTA—VLBZ!{r47tjϕ@ȃz+VM|7@<k$ 5U%/9N >'3cp)%tZI~zw9o=+}nx [xBi 8hBnT^+fn/TY0돺28'oUV2-`>a`e/V4m qer\mFbnƻQK�m$E7#㱞u4 P e\!M=/2y5Y0_o8UKG*8/G'<zB|Ҳ>䦼99KfSV�%I0h6L:̑f}~SN؏^| xpgmlhS٭,~JBk 8,-Y:PXQ|;eb223*[?v*.2xېo% #}ҁ~N|U�{x`w.T,WR ,*qޱ 8`-o|1, \;۫P"þS` k`\?ե&c;"dHߨML&VjTj *[yq8ۊopDF,̧6Jk\.%5 G[0w%I HaYqbh`D 597C9q;8GsT).op^F?Ttot}3Lw_(wr1F&IςU_q~֣u>:{Rc_aNΖsh[6e3|-6[ W-ruDF^d ΅spP  jm`.FRJVePLɒE-Vf^fdw:>\Fp̏K6N=öoL+!nƣ7@_T^y]Hogcs>vϚ:5F[V,.ƫ(~{,YfutL249\as t&5rܸN.oo\oRevr}{ݺKMflUWy>zjtS9;8fsrӋj9AC{sN|_ܘ ?]if'&!۸vfT !5K0G0uܝ kUp>+ 4rV8yEexE.<$౟tRQnE{;7zZCPD ]@Yi![(-%1FS%Y4 EPwс54hV*Bpam.1H^M({up0<Zo,&>ʴyZ!_4 }ș)<3epMG\qfsLM{q%JW.?{0Ã@mC9HⱩ e[&48"j@oO_6 7᭤|WwȎDDUư@[_ԍX hM.|H }Q繑0 Ef[Lë~HDSݱTǟ\ P|b[>8^!^%8/k?tB>!O%P+M7JGO#j(nRjesL7\<Ϯ &wCIo!jpxY/v-~bRV-ͷ�}a; 5l1um}W##軪*cL<(#β+[jP:KD�%mZg Ԩu?trmPl9 +CE +uS3.?y|? W|YϫPChW5Q# 0뜒FV+Y!\nM,E /e1xBNYQgZ%#H 0[QMr5F7vN2B9Q'.3fXd$*ǾhxrX+SUǯj<Ig9Wc3L,if9 D IQ;:-MK?袘vO ]Ue;2+\`sݪ+l/=e53٠!J,Fݷd@6T)&:3!\`4 3Z_gQV`d #ӹUcA-u~I\1uf#Xf۬}kN=r1=7 )3u'!;Lѐ5=1LT=RD 0\sۻx umb_3lfD4ŲA!Ϡ$s=#xa8noU ϒX~gOqV�e^ʋш+<bA8 ­Tp&PǛƲ0hd#FJXߦG *q`d9#Z~chF�vELhN-Hh: P{eou<Vr~3Z$ˡس9. cַ_-xޖV0NPzUZœf9\=ziG޸3 9X1h<ʷqk\rgq/lUH< LIUҶ7"\ h?}vom4۩I܌~گ?/W-.X̔ w† nj 2ʬ~Z׍~@8#n$ZZׇfd,c," 䦗Y8('/ZYkn�E\W5~x5;%B WESʄ(}q(e?;@[NR_١34OU]OZQ`{0H:U.hR <BK7^#Y'NRìT3N8T$Q]dH !ҭ]p^_"~y{ZeBNkߔY#UjJ@K,ȃ#z|CH|k%ݭ~E^GSw3B"Xl J)cԗ_-=[TaY>  7wwTRaR;<aWZ`v6p\1&f h?XST\Q1bga'qTz]+%+^ b4s$UD|{[2 ye$%X9Z] -Fʝ8[lw;gqQx<8!Ϫ&G_;,6%=#fR*LsKGE-V+CZmUm_z>j`?.M6Wp="cۀ];G{|s70M:1ɼC;<rº8-jûq~VI+M0iPt30:ALn "dY1 /F z0#ՕGxMDM7 *ö+qdIbe6G\oN^{{ȳcKj)c4zLYzL~2Y5ac (Ek7m8OUjւ͞pV; ēfMZk_h=>4[ny#łt%a:_5]{J7qQ`%m6,XjEwB`w_hYbjQTc�yðrl]mQ$L"&�f/lP/EB=]cx]@jIg&QFXҢo ͹w^nkkcL�; [ոϼI^EA<KB fli(b6Y viRZZuq~ne *o"đ?[q%XN>c_rgb`l_I-2BՖéZ7J-&8{B}j(2'5Pg4C::]_Y+.$EQڠ2z�w4 endstream endobj 683 0 obj << /Length1 1630 /Length2 17844 /Length3 0 /Length 18680 /Filter /FlateDecode >> stream xڬce&\YJ۶m۶m۶mҕvm8O1#; <+bMR"y%c;CQ;[gZzN4 ௜TVلfb 6102888`HBvf�rE5 **c0_O' 3[�Wk;{[׎J&&�gs @HN^CBV @.&35q4ȻZ[-LlL(�v��FvDK `�p71fndb`ohc`0s4ug;? +!{G6u휜- ;Ogsb;YULZSҿtaj ,l�&24[8[x_i8Yؚg�G3Gck'0 _7ݿgN&֦0 c9mfa CϬHؚ-7vDPM`lb C'k7$e>(o!7r+G%ZZ�{�.[=h >6'jft`"`kzZ -D-M-{/_nV� =)[YC˿U&t+:AIM ii͂ApVFsx0h޿ q02oB ?2Ύ�u3I3:J Q8:%_ oqܛ-q[ge8cL k 3ؗ5)pTԅ6Os~ux,HRcXK5*!(D$b: -8W^dW=ܝRP-br~'v-G#yG5JkCFjB/:;'K:y~9<>:|�*7�7(C ͕ͩz)M9I}م1v!㒉[�x0N*,68pBhFYR{Y|u3*k#9jY,e Y_|x1K34X\)CAC5gT!2y$Fه�F9}!\f&-_2< M9o$uCe8$_zKlr>)vM3!gD}n[VOoK `T.Gӈx%P4ol/s'¢aݯfj*NԬHֽd.,53+JA|{BzqG=:3zSZuF�WfiKA Hꮟ HwU?*(2R}hoW׬t``Lm W?ņVcFj`ʿy{Z$q+\ݕ&LIբjČ7Hװ 노78"=٣1<3 �Z9ԑ.^j~G2Y�+b)Cˮ]>%׼ \129ٺ[`0F x1P(6@](=Ѿm?> ۫[ \BXOוfŨ;5f Pۂ^X5;ޒ d*>}tܟiRMNT%2eà鑝VHdL *~ Q>sr8ǎwUR +WF'[ܛyV o` ~'&t?g>ҙ xԳ8QL,T,Ikl"V<=Rz3e aO~,brk=6bʅͱ w iD38=pwڤ?)BHFs+#X~s1JuV/zȍ 2UGȅ|Dc)�Oy4bV4p'Jѻ|z&‘Ϊx[7/d[�+awyDl'G\uKt'Nx+u6S)ݕzIm=!!*02 @42hz.; X1ѵA}Q*~{s1$ o4,:p giU ҵu ]0<T*cnIN;wKp^=0^Q*ՑP5Y ?15]IN4p (٤_P z)D"+,Pyq̺%6y$bf],lmH :wrl̖ Plv^t9szϕ0ujpq^t"Pܫ`ˌF5/YPesq@+4{uwM "%e!e=Q̩*!~Ύs{;>(z}D,]U.5y;t]쒋0ɀ|=t22bi?k$|%[44¦W͵G@)0<ol mjc_mZT8V<@16?QJ}l*pgވj9>1<90Aʉ~dc} s+&O<vM]8NU\fFїn ,lX)5y A]C>|Z^~LT!\/AY20ghy|e/&y:ܮS`hy1bN"B! ~0E29po|fԫH;T3#gfb1s@P+#_k G<b+ApԤfƩI 3S(Ep)_=#s%nCUp@jT8*%h ;G1 +n]Ntj!#nT k< #XH㡪`#Mڕb,<@ ˍBOH>{T`|As+LoyhMW,\E-KҬ o :y !Ps ݀@BFsL(ym'%*q0}v6m,_J1g[>q7OkG-=T4ݵ"+se gkzɢp!ewjT?f)xY~ۤ;wȥr${%O-6\o\:Ҵ k/^]3:->_1oWGXAB4ߝ!DO[GDe]XeU,Iv+zX@n6UkȁRALcrKCB@im[oDh"a*>զr׍wcX~fI@d,K@+fTWz :Y!+nip,q,Q찵 Xq}%v3S@ۘlgCsj$Ni6>Gubƣ5_A؋:<N9A10*6qṀ҂u "ϦK5˕-N]a7.![U2V02dKC%8hUXJ>Pӳ*)?OfߗZc|K0ō[ky <8LTM}}F )ᇐiË3D ظ''-&M"^%*~[~.{-h =9%ݘ{){i�JBj̤*]oR| qAK}|xN]Lо{P}`ivrݛH|p7\fi'ubmWKrr],bQy[SJD'8ܕKrԁhzPعH"igӉ /)2ͳG~g;1'TNdQltJ�Hhɇ ^>y&l ÅjeVc, W^k"8!m/< pQ[GevXϜ=qeN|_M_.ʋ\p3? 1&D/7KSk<!o֒,e$+®ty6؛hLp M<"Xh\Er,xK돶!7O jVdxЕ7y,j&?4OP~fX$fry!Y"�RK#zŠ+~P3I;Y`:g߫STd vrLٹ\@sBPE1{nYF<XDW,kF,Wt`Cvcm[VnSѲ@ˍTn<Y Q ֚%.(c%֩Z [yp*s;s)ߢX9|ۮ+=]_Zx0 sM0uqÓ0-&" bEH\%Kw?ZR̙gţ&#О՞?/mI;5R̸۩Ñ`aCp`z3);_O13ׄz,Ua;k[`ۡA%|>Q$viqO%=iT{}�"&qz8ͫ hEyg+]tFS~#+9y#CbU s$-zad[c*8å^LPKrb#߽ }w%/|y}^228¼^& 4'HWϑ+c|듴B QGߟDĢ$(N$m-ng\#>/l$k2DU5jU+ y)\b#8:8,6% 2ꆕ?.M.yM0 -=SH2ۢ7=OQz$5$ؔTxCKah7Lbj]WVo(Juӭdr-z%FsĽ >zd^.|Z:BٹP|C0*zlQ".zN0S"lc#f7v%wͧۙTuZ U3} a \BoS >n4!P#WkdzGk.:|")H){)F1S6wtlя Q"DXoD^ZN{wXKl އ)!cz]s,0bn!Ҏ>H=ZiO̖*~ncj콂?ܟ OJ{>/Z_aV݃NʺwvH�A5fZŌYJdu{)h&`| P5؍y8v}9uiPQEw@V8�D#$ReDϭŪjZ*y+5o桭nw<E;Za͉gsAn%^xh~o(Vօ9Z::KOQ ^3#.EOTteTE\gs2e΂<r&$ L侭x8mv^~b@I?mK2?DQ!͔yec:lpOA$N8Œv)NTq7zD䣻‰_wC,ȚCVzp;~q|vd> $*8f_M=&ik${~:4.9$d9I wgZ>չuI9p9g!f\(ѨV@t&oaW2(|k r͇XzN]dEQCRDemQS#xS]Ǥ D2V\5]*6'I02 6\hY<CV| ^;S'HPQK4}ko'K<%||ʔ/IIe!/~_>Nv~h"0fķ<zW ѳxx ž@]MECKPƜ(NQH?�́uxmJtxDk㒫^j{6Fk+t ~^8-1 A!5۩~kO0! 8]:%1S~iQ%@ < *o{ټrs_!X*Ʋ 3E>깹ୁ3�K'r= M. cPe_ Wm)k. j<9- w`+B5{A?%]0vy8gi�Y0c[kݸg1b1jrGRǪMn񽉋Cs+mnv^S*xdʷ̊0gi 6wb}64cFx!E/zt`+brΝiϕ aζԹ c_A$mLFBYߛ}6~'|Bll!6 ILc[ n~3U(o+/HR+.(B545UJ>Nd` pa{e,j?qdײ:% dvkx4X+0DYgq! b`=|%Lp89w#<5od~m{4DbD3<_[yqYY_>2Ȃ"ƈ Pc$gʿ*S^^UrH}Y>1<1{Do?u˩</gXE'FcJV�\sgwQ뭹߸LF.w7´DǛ%wA5M"B5˒wN20M|]5C`nb зƈi u8~w_@`稊1~u mVo4QgL:&woMjăɥw f̄ٮOj mȋo},S&k8O6Np+%gjSA�=PJ4B\Ʋ<BVra%TnGCЈuJAgԬ @(N;Ogcߐ[c>ټV =Hb)d P'tV0T4Etg6YL4yy.<ksf@Ty"fy^4zU' a6CН_d~eCCsz>Tڋ:##{jPy&]o:o6W]4 .a]7:Mj68e`aVNBȮI<T}db?cI^D0-őcR}a5~ׄL0;v8fz`j7OdrKʹξގ`gm!k)ԛ^; 0 r4 FqZn̽5̒n tm@rQZ+ WK A)VXHg�O$$@eG/qkŚ%ș7*ܞDy|omtzOǗ#1ҩ^];ͩG;aSWú-Qu)Đ#5P<f?s틞%׋CjRtUƿhhF/ {Sx*+k(E,361~7(P&s1<!$&-I?10iք>b[XFVh2 wu`( ) 'T&7Ol 0=mE Oӱpt!b)0HǧOHv㚀3W:8!COgx}#nxsoSCzLe?_;7w?=yH^|h:P duNJPaK]wN^<ڒYatzƒnVLPBY 3tehd}CLp o6BdL>V[;VIoI%AGoX`_a9OqyV§-8=t ?8I̘YAōj94 "TS\L-=&"+wL¡C~,3ᛡHVG&q8GN{g6t'::펨2ʰ(1M,WuU`WxO"k&#12@eƽպ$:BOgvʤ8 ؛,==|,5.`mՒ}BJ_ FgՒ]>LQEDg\43 PN^VϾ~C8J*G0 rGv3K0a Oпr ZɊQ$Cr1ޫ~![4,T{7U8?J{ ')@iDľ<!_peM>QLD8ߙ _CCClY,W^&S rnȻ׏_f#3dіެ( 4>p y~]U~S^۹ &�HBVpӄMfN€v_c7\|Xpr]IkH3`C!\,F²SW}u墵SfSa?lg@f<[O`D@ M1qVRҲ#n55%!Ul_+aua膣;$aVd}{ĭ64)_1fxza uƩD5N"Y}fLtxbrlY[<73`Wv$'Xb#nj~ )RgFPO_p~Kd~ԶU n$*x q؇qxhFldv-UkyN3�z;-7sʂURZ1A!2FYe\Y�B@~71S5ڞ3m;"K1壟F<C2�Y:v9(DPC5$''i!y?h;c3Zq&#J&?R`"1o{7)qY i V:F-=1w. }w[FLPlD?7^zɽNlUɭ*bVxæ!T(|׫4&jS?e YhT;yxF!p3·P6`W&2aB&~ ]4"JoKE_P,ْo8Yc.T>`8, %H\  A)h̥X3an3X A͇>ؗsZB3nziqLQBaUR6+ѿm ܟrf[6G w* ǖkK|lZl ߜGȀg>qn 8-ZeHȎ֥$:q𝻠m̠)]n Pez0EM!*|v{5Lx roDQP@jRf?t AfA ˝kwAAq )<r%Q[a> k9~0o!$%OLj`᩠:/Zdk4QoR%8yxs\]<7_[)26]mnjFV%'"iv~}C_%:{΅slS`Qy Bh'"`?gYԘ% ]8zmFx[<19piZb? @ld$amh?eHp }E {o=cS96gFǴ?T o֘ V<RP}i•& KrWB"DȣmYEP[;_-MsfcfYz�iU L$`fQ_`P>Y�+=mOf䦯V~b$NQSR(J]v*OmOZ+i]AjއKJlF{e4[ߗDg2/160zgT~C ~BL*O�5a=S>rQBITR44Dzjg׮3Ya).nW4V/8*kie%&CAHT?~jr1A5Hf-236>ÌdUMx4n~KH0t~e&U8Ë Q,_~K&eO~3j|ɕ^]7wL#1GJ 2Y' $>v8AR=\kV\5Όe8?XOsQ=}am2kP`|-S6/h C"s/h': 6±-HӢ fsRLZ]7GYӂ Qw IȰY&ޣvtVڻx&2b<B+y\1'Ea3(JRҖOÈ-?j'hH挽a% ; m&ʏR]ujXr'A n}pn_OwaI X1E S "j+_@E} hVCUߜ 1݈ Ѕڳ8S`e%݌BF{z<$o^Yu# hC\lNjW}CqJ^`vt(j=ԁct~1/ m^U @"ڕf/A"ġ]F`&n2#(Wԩ6>j:ݯ|K=qg.4K0c ]k*`~)H aL95mCM0 79fKrO򻫜,@ U\O|.ZBH&i=з^L8:#Ͼ:EjY 7 P9(Ja.E,GY1}5ֆq?Nm~rȼ$^Xfd%)n4xdY'I/yB bLl�4Va pK0܎L`NbwK/.S+5FaAYt{hm[a‘=)vf^BY(R+2e[0@~E:<(`(az{bkZ5:~C`;5X) iIs_|޷hq6%s,?>|Zv 䂊O/$#@{11W>S< C}!H%?! tyYJ*cK f)~|pP^; ޮii7`5f(#nd"DȆppT'Sm|Ef! 5 [GjFdq*וKߓ+Ɗ[_E9H⮬3A|h7V4Y1V90ET=<]bm1-{,Ѣ;TN7_}5}r\[ {=ƚ۬*?Xm5a@v VÆ[֕"zrɣ]@c@>q)ivz|$|kKװH0^OqCmD9,ya@iT@ McK]OWǭ>6 0i8a#LBŎdGb:T*fg¼Ŏe(aR6/nR&sLOĬw@3z"bҫi= 1|kp%J bQy7C*uz*11ۈBP 6 9*ęRU=3ڽGeh} {Ǧ3,+ }:9g,l/M$p:POV){r2 ɻODnkv2kHAUsF*sWY}q)W֝)rwuqXJjEf4 )`#B$1Vs5_Ba")c70t�hN]m !; \lyVU#s謺$^K׋o*0Zݪ$Sgs_KŨ 7Q2*C`.g~iIg|u`eٝJQ{p�+\3)ocbh/-E1:߂�)GLљ@NG u gYF(<aUșJ)0ǓPY  xgkNN!dĦ_@OɩWj͏ȋ!ⶢ*3/H^L .*I:i#Uy}J$(wC^L OC!b`qU3Q3K N,nӫ=V+xSiE\93|Ph'mC?bX^Xiܜ~{"]jqAAn$ *Rnsn 'OK(A1WS2NfH"@6|^݆{vN."dvoL fIޣAg@!){8oF՛Zaz )2)歱r.Cdb<%J=U#@!L!_'IЅ�;o@o_IQee; ٯ0kUzמq@=Aw5աaRun h=\9Uʺ@X9@4B&Ͳ<ura|y<x+?CgI,Q .›Ӹ9y_"Huﳫ\"jkWAz*4 DzV3T9@?w<vd<]]AOS,c"ZhA꫊ =Dz̽RDW8j5M]/ ;/RP3=-Tqhهn!$\ G`2(lu?; �/ܰ+Uc_o@7#RA(+oKy ȍb5�ctM ,f Ud<Yz-tf_ͽg ޏM;}9#;k'Bj%E 0x֛0P.VO?Qa/`8Cn#DPY,+5K Oq%t\8aSM84Kå5Tm g|\"|8 b'㘐T($Hf歾Uҭ@ T/$PNǰʦյCMޜb(2+@7Sa`7=TS@!U^βT9)BħvCb5)9 Nݔ\Jx^)#ƻLK^Asv1Pfߢ~~♢3>M[r-c1{Ҽ}4�FYFE5 zf:!I%޷Fo{6GȆ-67HgB]'p$P pME$l Ksl;znVfK-[GuƊ\IƓ4 L&er08v (. zvgF6SJ>spW9#F럊 49I!`Redr/1oY%65N4r( <IkQ QU7U OȂz)2)+WEq*RK󂬍qSE{V}M҅ȥ4 GV̟4kgFiġ^YQ½dC&�JbHh987`A %Kj\{m,yKSf-P_y[5LқPHH]uDoa=tG|&Q tdO.n6iYT_qTuT5K[2eK\fA:ءXpP6C䷧U.ց>;taȩ~jФ7M!=X٫, |,=C3ds/YQs ƻߴ),"I5hwG Gd2S` 5ZHY4ZI pdz`'Q=?b^ihрOjXRD2s=.S%D) e `$R4ɉA/%ca0yB`4ΤMQCI<"o":r0Aw[%B$>l94UΑJ*ۢr͑9Z`h໫~�M-%н!{lلu= /1| C7"h #o#AqQW|hR<6t0ج/Me|cJeT^ƆWѪLw?g \>GC=zW8zWՇrՖEhpT3Zxr.;1LxhύE !KOg8�qCc/ c>FIg.e>rjMm$Ԗ)wr[ 9'bzA5bj[qp n8o6eV/uTMHj#& * qB(DלNMR]K.Pxw4MJGaQè_/uq;|cc�Qp}Y4-(MA8@>dsjhV:Z/jVy)<ĕLC[I`)qA1}a*}>$HZB1lzkd ㌥TqZSx @Jb G"ŨW5dC/^J&؇ѽp!ͦ\8 .I az*䝟&S<$l,aYGF HһulJ(5f`7EB27W:`lnDoc#6F)/˴H=HĘ@~N`E 0X>bɋ&uoIAw; Ld(3 ^~#4ux-nGd,D+rbԗϥfpt;%|TdSh҄K|fk?  KƷ{ufcL (+ #Seח]H /)ύXP.%)8$6W\%䯇 l@݂5<Iy%k#X:O@q~J<bۮ2bѳ]i&`\'`(E@lJL,+ SDgni|OXka[nLB3ZihMg=9[rqa�>/G6>oG8҅RrW{z>DQ+?R!hA}B]s,l'A Onrñ2H,cD)Wg/t-٫@頯؞?#z j&iM% ocz& EDwܛB pAx5ӌ %*BNíp+CBpKI y!'0Ԉ7^جru,/6/UT|2 W*CaB"CX;fS(},:kP!hOaS٘gp%H"T5>WPw y":..bov5wXBu͞xП3E* EeMD!v7`[ nԑ:rY-p9.ƥs jbFF_g`aҭI7s?"#qdY8 I0q_(WRlrq HT'fr%2FB>Y9< i*+Yuntig /AP>ACOY⪹&r{.0*Y-`$x 7t݇.iL>.M ~UFP�vcPsnݫ?'*gSF2eonM}4`V4 ;u^u)Ĵq ]%DNu $1,}xMBozdGᯖąڌz)o$w 2 M uSoT6ity2M4{^V[x/fSwyc0p,~VoHC̳ ֐XZӯ;h;3+(?o$]>O{D� `z߆̗^q XG }(=t(pdNB0w⤤-RJe@BfX~5~΅;[ ud"m<[UKIŢ"|F7s. !j2VȁV NsۀzDL'gYf*iĬG{@?Uləh8TTfb])-=]VA۟+UMBR!Sč+WreA ȮL@V}ڊm52g$gk/cdh0d4jh$}7&}f,9~Vb\PQjkL:݌9N�8N13ē,P)RZCsчhD$TZAGmPF|ef5^&|zb0eIXNl#jĞ &!dׁuNNsJϗ-*|<u\ȆZe**!4R{}Q" #3U#J'{c9? ?2a떮;Iؽjo{7V* ǫ-O+|Q⇁ECӥѷĞn$s7e+D`Kk^aW!U5Ma%bwжNH"#z:K&"mh0)m]:_]vVj g6Uw$zH1os>Sw,ٔR .Ai( wy,j9{<Opm M+%j<\p1D\Rec`GiA烣hk$!MDz*DUڳ˽?jB wOvW~LO}!҈;1)D}R3u"79M"f{Xk]BonI_!` Y:(;ۏQPhQsŮLNYĞʯhI:k8{N\?^4Qkb9Ahl11Yn(,6/IHh;Uh;ƴjp1p,d`{t{)N/%ym?=�{t%8{Du96{bq=}iI(Tti6I8haժ :'x /n:N* DX2.~ooeN^@K"UGQuu{o]OMyI(yzL#E#QLM<\<7?QWgF%\#7z gX5&RcfO\^FĭgE 4sNgpzU1O (=aüDg|)?vO0 oK]/r,bŷ=2$@.44!ሺeʽq@r8A܏XJNܴP TK/{z .lX >T콭zҪ % F=N9|jT:|&{D]l>OV{(EEW]%7떾&4*v=όn, ŀW9Ԧ<]C L;^csKKyOF' 5C&L]>@c`u- KBj[`eQ\1ΉX@.0Ib: Y'qWа7SX ܏|` 7NC͛eSMX@h}ӫ+.,撃i86߆5v=T6"Xʜ{p7ՑKp<a~\sJWc'T4KF;e\,aPWLnofO8\%Iے^9VX B x]0,8 $Ýnh"IH9&vDlJ de8wJ LH[ؿC':# ' v|dE{󏉂x-l~͡w>Vso8l3>pCP"̊YfL*L)mmeOۡ1fϣv,- endstream endobj 685 0 obj << /Length1 1644 /Length2 10229 /Length3 0 /Length 11080 /Filter /FlateDecode >> stream xڭveXڒ-k4HCp!K #;ߝ7f]k*Y\YY&�Pٙ8)3-]�ovn$jj G3,i �h@3� arij322 ?7O'%@hk`;QՀ@`$udtҊ�i hb Pv1Af@`a�0%089�@on@w3 �t99}�&`8@`3[? -JFldrpEUwV&b;`Ms{3?%Ѽ& ')`rr5xF+ '0&@'77?gR_G g' ;[L3ؖ 0Y[8' tAtf- s{hĪh@S'AyoF_RpU4{w mɘo{ hlMZdM"|o�4W9Y,Ll]ltoZ�3;ۿ`V 3!`Mj`x(ߗ,۰6@R7<|�f>?'_D<+8;zl,llo>`/4R`3{?l6f.o_�t!}_7 NHsa v(W/M /7~fie#H-mw24؛7sq/հ5X+ټ.քa3T;#kխYJ] nFVMcû[ځ ]"ƬDjA|Ǝfa]y*204<]Ȩn7N8I-_!wMcNCC9 E$?v,/HX!7D.JRpԤ 3dHSь}'J-%)V7Z%VŰٛA R=20 ['!611[GRhmwPk x&+ }MmĬv;ݡ|$ ŔYk ͦJ2lJ@5>k+Bґ:(CVJ=~A7lh`ҋ<,'l{(H=ۦqMC qA8 ycjf{J خIgQw!ec+< / XICꚱ]KI9 _gPߡ>au.GrU͈YV2 $HJGRlWwu[Lq{<Vcw9eL]WJn; ;`Z'M[W@<eNqe@6$I}%6l'\((k[E <Gq6^9Ar dvqmE{\fDR`5ߛ+%U4:ֿ"jٓ.^ѝWl@KI5ǂW ?2gZ]G[<:[ \|ᬑ+9y_0wUS9ڿ+@Y+j귉~I vDs4Zc& zMzM}FA=dyB%;/`jۋc̣qF#$$=Q'.՟uPL3#9gjmR}wj͇ y<̓ى%x»ӦJ�"c؂.3jCq pBzьK,%oIn+NL`,uW4Y{KM$s[x٪1&Sa4�f:n3B| g u-ϡLtigIO/,Z2\i|_-ox-xT,0E]dfY^ŻN#hлS@~>n^M[\=:K9xH>a5e>!B Dm<;E8:\7e_&1R*3bG]5eY< ~ك! 縖$rR>d(//qh-ſg+R~[ ];IyrZWSs8ˣт"H=[ ;[2>m>姆 5sK #s6JWd/O&0v dܿkabUd.4o+m_ ~쮃m-`g eII\e YR gGc[&@䩖9OQe=eX̜w(%@65x2eAʵ[CC0B�wy%+.In;6ܠóZ34IfN+t8km .LPҗT/'jV2?` }T"=zJ/_}6%῜v;Dn~Ϫd':],WmT|Z >OOg#N afץ4:BN5A>k#' :lv& U" tER͊hD$qج0}�7F�Oϳ}@L?F2}.#|&zWK͘"XD6ӘPiFou +N oJ mqh�Jb]u" g8ȣi=]wxLK0PgZ"tD 3B:T<>TjJMqtBܷ|8<E?^wr'#dr:{EtJFޤu>R{lC,lRI>U|_SH15H\8BŞz~Ѭ6ًpeEsa?0Fo7"ڶW2ed]t!w<^Fץ4t o4&m_STOG'yЧF-fɸ& W @Y85K}0 %$YY^?oȏ}tfqQ%u1Hhℰ"wҞ6LS/PW)fp@JtfWzׯ'lP 㴛^"yEa[?-5Ɩ:J 5c nKP( H{n|&9o"6'eO(|7fbN$RҸ %SfûwOJI34%+Q-|IK鮖{MϯF`?\oLL,2@ L R~1PIdM۱i4y@k@11 �Wǖ0uoT(3ԳGq#"_](2p״@A"/lᶒ_e)c[fgE2QZp4Ug#؄^>ŴP?Kex4;6_C]{(@͔ jsiBJwȆ�s[%w=:#IWD~Px&Y^3vfiYy& zZ#ia}‹4^N&maR8Kff`]+cAH Gm'2D]6N1DyGJݩR!e)B3.؊{o]xG"X MW7R"tHnR\ĸ͔Gku!&)y!SX>| $߳?SZ7)xH3-WZLyspC^f+wV {fC}zd(QK) Yp9vA^H,D]옮[14Ehwc{SԝoTC«|FxZu4*g^w(vN<LќFiy:h?wj]NfcPVu1^ySKIgm{QuU<QDA=$f7 o xO@moƻRL)0HORGړoeGKԲϔwL�vgS3+%bNFțVgHy:<"W۰1FE C^Pªilp.ZSאڮ{x8S+Ԗ|coS'wH?S֬>?ޢXl;_; .e{ю!FR̞XJYKnQ@mY"lUAFа6!/:$[Zv:}. iH9)X*koZG}) V$ ^>FGIZ* )d*+hPAu;ǥbD5W2U26ǹ#�WQ^ X>[bnة];Q\E;aC+xALV€:H>" ԥ EٵVi^q֌—RM R52n=KS#N׬pSNH�A%hg417M;E#Z | A-B:b(ST}R4 {>Q7)c dUwX CD7:-! iWv1z*-ߖ")[쌈7ہra>BUc!Dxө;T9N-Aٽ-#9?m s.99egn_1=Kϊ! ,7g`)D[SLVCkpeC XDYbffcF*q~F�@8(fݷ_),W2^>Bq]ˇ~3v}^Ó,NDqn@:վ>D{RsHn9GyՖKZ|Tq02+'n(yceqRIW4uQa[y%1 U- "<rZ%ؽՠ+$?!l$\˻7Aglf?in]/d(�Ny :t5|q>U\KhNhO+2SG ^&MxD'mM`sՆ}7G+jx_p&_9\ ?ۛ4hc 3tZ!YsUR~}{>n9tLCF'>Uϊ#I)).D.pt%GN+1E96&b͘#|plLiyr^-cK١ٿ5Ж@m_p�Eoal5IYFiS}ڐKÀKpA1 <Jc$=tl%yW9ŵ`׽vp=%ڭP/ v]’fԪFnk. u215Pyu `Wg漸vYU}i?FTqpcCݹo:*V!=*j.,cncg{%I󝍻Cnڊ˵8W+z,-S)p}9NWef=9[ir}?o- ʌ3_J 1iTm\t簠G}Jī#>#C4|.t[NIgvN3sd4< YazQ1qdr/ϴB6W"_l}T<]@>3\ѐU:S8U'F`#W.ӥ_ZPe2n3٫O(_K0WaY4-6אP˨5/u;{j6']N/*K#QȪt(-0 4i!*rx)g5}ˮ5zY҂!V 3ݥy܈ o~*@ǁHP[N~Q?aݎs^U9+`w ttNIsG9C�0f%O^ hQ Gt}5iiAbKMPh"(O5[҃!鄙yso'tjh~OA|:bG#κa]—a>O ) S\ZKw#UEsYe7l|d wGA̗.Pp@ . F j4Adnzza{J&6/xob(* ܢua8дwnNPPRռh]D\!yshn 6GK6[")jp֤EEc2{Ս#TGkO ~K!m}D1"-KҐ>J~N>\�wlyp Mj_1ap?o�3@=hh(l3Dv=IX'n׻ڀɒK|g%˞]^QUM JD Tj'.*)ٝkGeJ%9%}mMEգ]ٮV}GRP™T/4ZiiiOBu1{<FnM}r8W~Ƕc!2r2[ϢD5.1ݵV*}ZFP$~13]V]9Gi`If\аj[Sj?ѡ8Xŝ0GK'esl˭0ɱ:&44#hM876{r7]Tv"e<W*gB:W ~άs_&HKѥ瘒(\υ%y?nY K]  5<2]s;| bJV2wS T-?x՟S­h0Ea?ԯ$2mܨք..:EѷcPe!%R$np` :b?ލp^(֜͵`%K(C;3SJh!zE%ݹ9儻GHA.xcZ8sԊyPx;P]7{b>pB*ݖubӥL *<$U?tA0v^1=ZUu?GA$^jQ.")BڝϨ:[Zd`W&tCԼEwJK|tޗ'2F^wϻ(2Eh�]<߭:x>g玉5->x F8yHR뾁lch9-Cؓ4} M4ʷ s- ̟tyt:<H {@mMN('i/z>v7}B]B(|=DdXv>A*@=m`B{|?)H>+ SOyA(c_g<uU@K1tb# Vms2yZO$} hƗ)(wVB םq0~ thҲYfICHdWYD%fd.V(:Y|*?~4lyݚ܏9Q�\T6>F*AN%dƋ*A{L2WK5axIX{w).r.=h'/Ov( ?_0=sSUǝf�2d~ q2 ;àgFYfp  ̣'HD۶͛)N} p3!Ghڒd 莨gW0_xׅ>II&OB}/EnYa|FN湅x:ѓ5ó %7䈷ɼG>έC=ݲjܥG-rR];e .Zii!<jI{i6πGqx0=Ŋ2x.RR"; >RԞs.%]3Q25Zl=ZKHE,p2E:+ζ;tݺ*{MKʏ( e)l]1?(ʮ!Վ^Y$HXT*j-JL8^$ n$_μלz_!~=vq):@-HJyBƶAqIߍ7ZĄA]Dr@'ϗ [V&k_3I4e:'M>HDȣl0zM~S(C|Ƈv<kzv1/A>\EN qMUeb M:3wV 0Q:5㲕(HCӨɔla 0:xoL aSg[J65WKIw[LR3',CFF7={)娔3yaqpk[ZM,q_kꊷSGY[gt_C -wK7[v}ZhIE-dv_ Xxv+f){Y8K6//Q+ò\(㍽G& &*eY{Nj/{Z]V O<U$# ͉nS KHmJ7dhaYv"߄?-(UgIRnwtZ%еhCCh>yPaySL\&%/iY7 ҍqCX]lXqћ"=>(FRx/gqYG$ȋ:8;pޤaö?.G:\I&׊&?�HVWnms0v{ [̚E^c=`O߄񴢲]9)Ag;Yڗ#A |lՊ`S6ѯ6^8q0#q8!G}ry"N>U=Mբ/ ٺJWx2 G?*̫PQ1ʟE+1g(~WQ!s7W"jrQSK,BR[g5|]ѰD(HO^;^F/bgw45k|0Rr򧤵v3^>~`]cj[Dq;@VdSouHh\!hp~E<TWnc^u7xT'?=N3+pG}A5 bՑ{N,~bX'IAK?g-=)؛)y,^+z?UDɔwX$ X$bu{:$|/KA>}aK q~2ߎ9"6}.y P?oNeP2`mM H=y_rۅ"Hc.5~AN,;Z2UC?G\Ru -VY֥bit_At\u Ost#ҴI].%<sŨ�n-Ǫ} G?gw:vu&2%A|ST8T-'�´V/DtQg@SPӝD 6uu&rf]QcsV'a&#K @�1lCjiϊ2U$Z&+[Cކ gͨ"fXjF>yfC͔U#W4.7FS![ QŸJhndQS}VP=ۦ3ϓ)NԭTrd]=aT{M)_hȉ{Z 3 ?TqJoJ%S*`hTgXUc =q|fj8*Q%vr|'~ʫw͋/3 >y/ZaaV/M o {؟_7T~S\TJ(bcT=jaP\x"nc8Uy#\g>i,XYYa2)7vB >dcܢQ?Q (X}Β$rPI>@ܱ7DG$['9e@jcF#sKPbhĝOR{+Z%~@0-]rYvT?X&'!V3.SҋBAW<n0iLEuG"?Ce�%,)Ҟy[T4c/m?Ǿa%9E¼> = A6Z ۤ+E!F4 yҎC+Gx0K#ǣ ?GPI%Ѱ̱8зZ,EUk/f$'lU":ZrGs*T[ 8v7;64_ ͨ(+83'%KnXQUӀ"OX]B l;'wX{tcG^xu=[w܄yNukhx?͔JFy5B/Nn/E=N)qO?66jmІ_Qh1ݕ'Q.Jp_ d\T ovlc159S)W[4UIc|ƬK3F@.w㴔H/$VZK8δv5]/{Z2fer+ϋȵw6`r"mvЕXmڌ7RߍXGh<NU�k#94�{ygda3;dh;j_~ D1e0vo,񫆋$^ߥIK`WT uFgae€s"G;u%/ag~px{/_jP_/)Py=yf~T@ZV=R*?n<m endstream endobj 687 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 632 0 obj << /Type /ObjStm /N 100 /First 901 /Length 3341 /Filter /FlateDecode >> stream x[[o7~ׯcC nܺnji#XF]4~ùhIJUaH8SP%#Vh:aRBhޡ"r-^)AtH%7Jx+t +'(h R1Qh$vLJh:$8aR2Bc6*P ף0>%a\\Z @k&Z3ؤKV[5{a7jm%{6�Su{c!tEՀlx" 3[+#и<cl11-^gib@EPXDz9i3x,)`h!jxp?$qE:E yևA4bd{D ,hC`)sˆ@Bsº ֖k#)(P(~נ%'54n 4@&sic&~'K7,N3TVmeYLX؆=P(;krJyX}=&(҆ MrXxC'@IƱ u2QRȇt1E?Mtv^N,UO|tBf ʳ81>l2E q-=y,gS!oeA mC(]P@V}*8o)X6*H=0�.: QQha.L A<^6"',Y !Pp[k h? Lu  Vq@<FD 7�S(cѪfJ-J稈hW*}ƺ4Ba^%<թ.4mU!qUl#ߎAoyqˡ'b<-R?hL8h%Hc+֔ WPKdXE0x_H7c2ED"AU3E@0gu1Bl1(K,b$"rh$F)"tI#t�8qS> _EB Ҟ;kW<pV%{ruZ#i'VHaց TB!s 8NB8oڰ8A07H\0 ~Pl�OOǤ(6x?!BP R}eedC8P!6@qd=4P"ɷ#<|h6 ɷiCM?ha0 Y4 -Uw +xC!uނA@7�É>NGBxJp|_,2r<~}Xĉ7údk{ېTh7)Do@O>MώKZȧ|V~X| #L[Nsי]rvVa~Ky>N?`@/Efnp!YDsL'8} 7_m3.m5wZ[]5=[ӳ5=[ӳ5=[ӳ5=Ws5=Ws5=Ws5=Ws5=WsQMB Gx \k8ڔj= xi@H#o Ωz#l֦Py9@ Hg"\O;3I 3  +έ*-a=ڠeDpOI.|� GR?4A%#XX"7Iű`78V|=Km'tޫ]qA<N6ZDj| C)#ROLܴZ#꠸6\ x7m!b  v5"lA@#b�+}MD:. o l6m| GP[gZtAY @(LT?)pI߸ TKX<ߴȨdƙ�p'q(ټ5 : ݠ6p[N(] [q KaC&�eMZ: dDIq P$p NlW?h0x*Dwaئ4�=l+?hv0= OۓXm3 f6ýwNH7FNhU}}Ϳ_3 _{;ßOL>9eHfȿ}[OB~yf<LtaFT]It{}2>._ǙM}KZ>`96<kc[ o4HI.?l>d%Ij%I$JOu1NN3~+4i$\j%T3GRj@rZK+J^g`+qЄ$Vur_smǂW, 2.�4hFAz~ܘ [?Xjuq-~ȱ]WP;1fT+,WI7+ske͸Z]:y!]]aHJu}޾Sco~oߩ淎0_weN?z1USw{l:Osa7v볨=C|4~R.. W?_ ǣqɷNj9zuo_g~#]H>?Ƚ,/P*#y,s|!_ʡ^]pr.E9BLΆgoŸ|h3Qɳx:߫<Hdn9xx%7|3]䅼 ߗsPC$/_חD[9r>Wr"'I)'˫S ]LTNZ^]F{gNq;r.wrtQ|l0fr.ըZ|A\,ϩ\l:+{ r6RRԣvW///I}VKvt;ö&(JpkY)%/;d1Hj\_Wu<ir~<dKu|hLJe2^! mBMn>Mw}GJ__ݯu4:>[e]>ǟDZOK.nY m>lveo`?>60lsWS uDj7(3\džաNhM=fk]+pt݅.r:gxI?rw;˛RxЛ޳|_]͗hGOſGe}IPV}(ȋ ]\;l6Ӫqc_u= xQ aHnʧ5^m' aȵK0ˮyeUvn8#,5Sd7|f}nx]mws endstream endobj 689 0 obj << /Type /ObjStm /N 100 /First 900 /Length 3982 /Filter /FlateDecode >> stream xśos4S%"KuUG dQWΌ۳-{ْUGUjQ%*<Sf"R23TeQg4YFqfBhC38\pQ3u˘2L8\gLd%BYhQT eТfΘReQ*0υq4 ^٘G91`(rf줤gU12)@E6`g)jx& 2"܂Z 34=R :�;)%!_Ep )3 )+2P8Ձ?iB 60Ri Ġsis�'J3 4B9aTf$Sp .Y WCX]VQ5MwSF#=ԭ $4Dž՘9TÕumPXL3\rA L0V s@:� \LO KA8S*se#p-^LcRGc)•bА3TRR@#L@9$JjS),?3oeFh6mܟϫ-Med"w55xLҚ[u[zP\#$'y~{ؕ y-ۑ@MI7ڲ$wc "^IW1ps 4.ܷez@Vա$g9|A$%_LK "ߒk򂼄d$7|O~ ?m[l~){'mvC[!8 rK6dK@1';R_HM!@~%-HO5yCowX6Knu]Zog&\o Mـ=\uEr]Rtj/@zϕ!E ,4᧷C* r[,ֿO./ZXoڽY8gwogEWbOFO?o_H3gym?u@ojgxV W_~}Gؽ*oc(6<$C'v Lqa_>~rvs_ߖ*2g_tyuN,ܠxwm}QG>-2Ϟ?ꇈ_E*Q]3T^}so_}t NP}{%̺h#h@-3[ AZT@{Yܗy~8wo-J\NÙԭQWBʽ}`>8sݽr: \5\>ǹD> :%}9ɆW5&d6\CҁK1ġݰmP ܣstًc_s1#{ sx> `J>tGrszٖ󜟱a"9zC'M _WWTWn'_J3_,K>bI_kT5Ѷ)V<Гw;ÞGۉMA7>sAn&&mhl6f"SOD@ N>h':Yu8gsjRYE8Lq>g,'2YU8gsb,RYF8Hq>g,&<řE38gs|SϙG83Kqf>g&,řY&C3pvsnOb>u>jpGGIJPq?U_94e>k.X_U=lص zq_as܃sVK?Ym`$WBg20u؏4PLqlO4@]l_?tV{iҠl8f`N]n8tnMiKܸo؂̍oз|ҕwHh䗁GI;"]:s87iZTw<wmQocb f||rfӒ/䑾aQh d=GoV\leZĚw0-`Ǧ=y  ҟFD#zoP{L_vxl_vEaމC{|x"XGL|:-뢯^H#)/7m?)j3R9103q ];*[Swrlj(e몍&G#nUlV:b3(| FO ~rdܤ>珏Ķ}}~6՗D&c׏HzsmV{qnTc�ЧҰ:H(1S\lme1wU3#E Aċb:uID%S<njl}T+C6MT?C#00is;eލڡ<4ecEWx4u;;"7ϾebG&NX\<$ p?Gab;=$܈Krɬ9E4.im$q< KWbpӍgqY V?LTi(R|N'" 6tz6Jƻ0֖Eljˇظd->ɎN<9uҗ2#OU.vOҘA?+M6mErbIxI8hB{\zVws}%܌ե^̃xS8I:p"|0bC\O5ZH;x:> %}$xxpg7>\cr{?7`Cc ;d@{lvC_:u=Nj!�6k@SZf*Aaо~?[PEb [pE+9:Y3P-HPbH ЂQu'.&E<1c}`LcaVDᬓՊ0jj)>Qɔ/S4<ɞOFqIWWB7| KqvYwu43)=f4*ufz9a{X8f4+lqZr`ssMsT�$㽰`AZ]+ fo Xl$ Hcő4 eGҀ4f`a,�in! m2I $YkPq/St)X$2<=3{:A`m9~+'yB>G"EG"#gDőHL&}"�0E[AXC=Xe�`kb^>OT㮪wf=S<ƤgjƘLzy`3O;3K,b`\g΂-�t],Sy)łK<_ y P`kWb:y'+tes˵[k "Lw&3^--[- Dl3@8R|U8Y'#ڠ D+iX ;6H)u(ff["Z,e9V.J"ZL*hU`z!"uJ8 *Dz9-Q!mpVHɬ=rvUBf[!ZFAS6(J HdKyUȫ,tnpHOAk|>`쬫S5\3EP<4>RGWOAI@Q#%~ճ^zOq}aLh:cX&AJb=Qf nR[A elP} AA?̶m`2f\_`2`SE)"<FuVoS[E*dU ɪ@87֣85XX)o1[N`z<us?&I9Lo?^W3Z18rǒ}M@y %X endstream endobj 754 0 obj << /Author(Hadley Wickham; Jim Hester; Jeroen Ooms)/Title(xml2: Parse XML)/Subject()/Creator(LaTeX with hyperref)/Producer(pdfTeX-1.40.20)/Keywords() /CreationDate (D:20211129125538-05'00') /ModDate (D:20211129125538-05'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 745 0 obj << /Type /ObjStm /N 9 /First 69 /Length 313 /Filter /FlateDecode >> stream xڍMk0 :ձ%1XodChM IXG]YO6!G8]ti2 o#K,6`w妅lN9fuT=WBޗ؆Saݕuu5S+X$avf45[#[b d ###o k[ޟd{{{/؁qƲ^_vgϦm)pYMvx2y|nۢ+vVxX-X * ]؇6uz&6c[d�j>o$ endstream endobj 755 0 obj << /Type /XRef /Index [0 756] /Size 756 /W [1 3 1] /Root 753 0 R /Info 754 0 R /ID [<D0D4B3F846D0265EACE982669C262A7F> <D0D4B3F846D0265EACE982669C262A7F>] /Length 1750 /Filter /FlateDecode >> stream x%7eI7{⦅wgz7"@"JHl@$D` � 6،By}US禔G)RNs~1'%4em;d8fm;h8 f}&vp#p =g8kM/#p1,[.p),[#p9;$p%;.p5)p-{$p=l5o5c%m1 [֊0ynMC;b}1U,ri =bWbq8L{%[Q}[cN˓<8*Bl18.],tb{VSbOÙaClY8\K0SZupzv̆1\p&܆;p}x�LcxO<^kxo>]iȞpLKU)X->eY(]{xa' p ^8m+qsˈ 5R6XδFɷJ:#ES1b[dYe%r~]yrLYoaP}LeʧU92~ǫ2J*<JݺTwUyiXLTQ*!UAzcʱdN[T+VYkC<v\p` -�.7r:xkk?W~\N^fOr:ݘ+?W~\sʕ++Of/WA7( ?usa ͇fBnN]nINߏfG^ Q[ QCݍvAXS iOlIwC^.>0(P:՝�; ZwY8[ ܆9M=~mu h<qC m@Tg 1[x%b(&??}KзP(Aeзo{P["fȅA;aũB9}O PPJ7vLٖS"k1ACܡqQD"T9 } } } U UM8ߌ-- reeeq(e",Ǩ_ZTBBBZZXKݐiN?PEyT-T-j\ le_wbHFF6]M6 ۨXS{lhKsreeM6iڤi#hH�hlDis1HF&aAA-4mZ&g9}ѦD_B-[ loA7Z6Z6Z6ibmm|dhPQQQQQEj&M}[4U+ m#m#m#m#m#m ik}G0t~.hz-]?Y Ka{ _WjD~}IoͰW^oۇgrG>�=poMQT>.N)&hs4"\ˠaWNcO4O3/BuN{οƧ9_e|z?*>}/7ǜg?1ūe(_?=u`?[?7St?`C>DO kpn@F}pB5۠tsCxIsjC7==|S)&8)>E)b)b)柚G3?`4c endstream endobj startxref 152767 %%EOF ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/�����������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�14147164547�012313� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/tests/testthat/��������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�14151433702�014136� 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�00000012716�14147164673�017062� 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) }) test_that("xml_find_all returns nodeset or list of nodesets based on flatten", { 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>") y <- xml_find_all(x, './/p') z <- xml_find_all(y, './/b', flatten = FALSE) expect_s3_class(xml_find_all(y, './/b'), 'xml_nodeset') expect_type(z, 'list') expect_s3_class(z[[1L]], 'xml_nodeset') }) # 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") }) test_that("A helpful error is given from non-string xpath in xml_find_first/all", { node <- read_xml("<a>1</a>") expect_error(xml_find_all(node, 1), "XPath must be a string", fixed = TRUE) expect_error(xml_find_first(node, 1), "XPath must be a string", fixed = TRUE) }) ��������������������������������������������������xml2/tests/testthat/test-namespaces.R���������������������������������������������������������������0000644�0001762�0000144�00000002632�13654264603�017371� 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�00000006215�13654264603�016764� 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 works with raw inputs", { x <- read_xml("<foo/>") expect_equal(xml_url(x), NA_character_) }) 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") }) test_that("read_xml and read_html fail with > 1 input", { expect_error(read_xml(c("foo", "bar")), "`x` must be a string of length 1") expect_error(read_html(c("foo", "bar")), "`x` must be a string of length 1") }) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000007562�14147164673�017277� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������context("write_xml") test_that("write_xml errors for incorrect directory and with invalid inputs", { x <- read_xml("<x/>") filename <- "does_not_exist/test.xml" expect_error(write_xml(x, filename), "'does_not_exist' 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") }) test_that("write_xml returns invisibly", { x <- read_xml("foo") tf <- tempfile() on.exit(unlink(tf)) res <- withVisible(write_xml(x, tf)) expect_equal(res$value, NULL) expect_equal(res$visible, FALSE) }) 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.R0000644000176200001440000001634213654264603017342 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/0000755000176200001440000000000014151212037011717 5ustar liggesusersxml2/src/xml2_url.cpp0000644000176200001440000001130113654264603014200 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.cpp0000644000176200001440000004471714147164673014350 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.cpp0000644000176200001440000000240413654264603014345 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.cpp0000644000176200001440000001442713654264603014752 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.cpp0000644000176200001440000001601513654264603014152 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(base_url_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 Rf_ScalarString(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.c0000644000176200001440000001703713654264603013053 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.cpp0000644000176200001440000000664414147164673014544 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); if (TYPEOF(xpath_sxp) != STRSXP) { Rf_error("XPath must be a string, received %s", type2char(TYPEOF(xpath_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.h0000644000176200001440000000121613654264603014244 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.h0000644000176200001440000000745413654264603014221 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.cpp0000644000176200001440000000247313654264603014605 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.win0000644000176200001440000000056714147164673014240 0ustar liggesusersVERSION=2.9.10 RWINLIB=../windows/libxml2-$(VERSION) PKG_CPPFLAGS=-I../inst/include -I$(RWINLIB)/include/libxml2 \ -DLIBXML_STATIC PKG_LIBS=-L$(RWINLIB)/lib${R_ARCH}${CRT} -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.cpp0000644000176200001440000000351713654264603015344 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/Makevars.ucrt0000644000176200001440000000003714147164673014410 0ustar liggesusersCRT=-ucrt include Makevars.win xml2/src/xml2_schema.cpp0000644000176200001440000000263013654264603014643 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.in0000644000176200001440000000020313712532530014020 0ustar liggesusersPKG_CPPFLAGS=-I../inst/include @cflags@ -DUCHAR_TYPE=wchar_t -DU_SHOW_CPLUSPLUS_API=0 PKG_CXXFLAGS=$(C_VISIBILITY) PKG_LIBS=@libs@ xml2/vignettes/0000755000176200001440000000000014151212034013135 5ustar liggesusersxml2/vignettes/modification.Rmd0000644000176200001440000001175714151211500016256 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 https://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/0000755000176200001440000000000014151212035011327 5ustar liggesusersxml2/R/classes.R0000644000176200001440000001530413770665414013135 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.R0000644000176200001440000000453313654264603013160 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.R0000644000176200001440000002400613654264603013642 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.R0000644000176200001440000000115613654264603013310 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.R0000644000176200001440000000127413654264603013615 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.R0000644000176200001440000000607213654264603013342 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.R0000644000176200001440000000412313654264603014652 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.R0000644000176200001440000000041013654264603012427 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.R0000644000176200001440000000405313654264603013273 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 #' #' @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 #' @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.R0000644000176200001440000001560513654264603013472 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) } if (length(x) > 1) { stop("`x` must be a string of length 1", 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, base_url, as_html, 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�13770665414�014144� 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�13654264603�013344� 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�00000007200�13654264726�013510� 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) } invisible() } #' @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) } invisible() } #' @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) } invisible() } #' @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�00000015515�14147164673�013304� 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 an xpath (1.0) expression. #' @inheritParams xml_name #' @param ... Further arguments passed to or from other methods. #' @return `xml_find_all` returns a nodeset if applied to a node, and a nodeset #' or a list of nodesets if applied to a nodeset. If there are no matches, #' the nodeset(s) will be empty. Within each nodeset, 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") #' #' # By default, if you apply xml_find_all to a nodeset, it finds all matches, #' # de-duplicates them, and returns as a single nodeset. This means you #' # never know how many results you'll get #' xml_find_all(para, ".//b") #' #' # If you set flatten to FALSE, though, xml_find_all will return a list of #' # nodesets, where each nodeset contains the matches for the corresponding #' # node in the original nodeset. #' xml_find_all(para, ".//b", flatten = FALSE) #' #' # 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) } #' @param flatten A logical indicating whether to return a single, flattened #' nodeset or a list of nodesets. #' @export #' @rdname xml_find_all xml_find_all.xml_nodeset <- function(x, xpath, ns = xml_ns(x), flatten = TRUE, ...) { if (length(x) == 0) return(xml_nodeset()) res <- lapply(x, function(x) .Call(xpath_search, x$node, x$doc, xpath, ns, Inf)) if (isTRUE(flatten)) { return(xml_nodeset(unlist(recursive = FALSE, res))) } res[] <- lapply(res, xml_nodeset) res } #' @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�13654264603�013334� 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�13654264603�014501� 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�00000021453�14151211765�012242� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# xml2 1.3.3 * Hadley Wickham is now (again) the maintainer. * xml2 has been re-licensed as MIT (#317). * `xml_find_all.xml_node()` fails more informatively the `xpath` parameter is the wrong type (@michaelchirico) * `xml_find_all.xml_nodeset()` gains a `flatten` argument to control whether to return a single nodeset or a list of nodesets (#311, @jakejh) * `write_xml()` and `write_html()` now return NULL invisibly, as they did prior to version 1.3.0 (#307) * `XPtr` gets explicit copy constructor and assignment operator definitions, which were two missing components of the [Rule of three](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)) (@michaelchirico) * Windows: update to libxml2 2.9.10 and libxslt 1.1.34 and add ucrt libs # xml2 1.3.2 * `read_html()` and `read_xml()` now error if passed strings of length greater than one (#121) * `read_xml.raw()` had an inadvertent regression in 1.3.0 and is now again fixed (#300) * Compilation fix on macOS 10.15.4 (@kevinushey, #296) # 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! <https://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�00000015651�14151433702�011454� 0����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������4529ee27355310c3daf6a309e42b1980 *DESCRIPTION 189d0ebaa4fdd12d86768e02165c8ff0 *LICENSE 4ef043cf1dc65acac5b043732b3b6ae4 *NAMESPACE 8f3fbbafbe9deb14114956431f3da90c *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 eb72ef786e5567c94b0a45b28557bcd6 *R/xml_find.R f55565b0c494a126a91a34a7fbf7e29b *R/xml_modify.R ce795a7c93fab1e2a84f588d43e2a221 *R/xml_name.R 55979f8f8062620fadad2f23a5e54b26 *R/xml_namespaces.R b504c70095213c90ee91ff529648fcf9 *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 4590ad4d7d433ef5a03b0a71223c7222 *R/xml_write.R ba02edba719f666ae5dffeb962b215df *R/zzz.R 10fae0ece2746442da5bd685e3207f80 *README.md 300dbf676b5bf7a6a8cad5c1fab0523f *build/vignette.rds 4de421c71901cf90dba170e724d2ef74 *build/xml2.pdf 6071edd604dbeb75308cfbedc7790398 *cleanup aff3b61b4f91a3766a4837768b848cb7 *configure d41d8cd98f00b204e9800998ecf8427e *configure.win 71e4c691330a0c3874257f80e782e091 *inst/doc/modification.R fdb983f74645bb473ad6cd64fd4cd8de *inst/doc/modification.Rmd 679bd7ff469e0de8fd18dd323887e9f8 *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 cbce861c6d3990483315617e9296acf2 *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 ec9fa76ad706ba6d3ac9761a9f36cea5 *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 784433a4e4fadc2637967f497984dd2c *src/Makevars.in 2cec33791efd347cbcb051402d7cf9c4 *src/Makevars.ucrt ba391f6a383b000ddf2cb37da3c1d91f *src/Makevars.win 520c2eee421cefd566346cfcb1319587 *src/connection.cpp 5e1d636b082968e0fc36e550fa717099 *src/connection.h 8ebd7cc3cdd0f50f258be7423b6dbea1 *src/init.c 8c29f69edbb86a97b03bde32b6affb6d *src/xml2_doc.cpp ab9884c004dfa9d3821cd3fb265cffd1 *src/xml2_init.cpp 1253d3d96d74f3b07b7f88e063124848 *src/xml2_namespace.cpp 8e91b630bd9561baf0db1a183ed982c2 *src/xml2_node.cpp 20d5f8d664d015d8d9213e640152b19a *src/xml2_output.cpp 5d8619e181ee20b058195012c2ab7d6e *src/xml2_schema.cpp 6c32da6997f59590e214c7d73d5c728f *src/xml2_url.cpp 2e4637dc959cfd3e82b344d7ea143729 *src/xml2_utils.h 82de9af9c08c23db98ef313ceb9d28a0 *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 6196325625771601af27e2c995ef26b3 *tests/testthat/test-read-xml.R a6d0b66b125036ec9913ad60c214c663 *tests/testthat/test-url.R 3486b2e39876fdf5663afdf4588b5ed6 *tests/testthat/test-write_xml.R fb3d5beea0df836135576cc80a127b40 *tests/testthat/test-xml_attrs.R 4b2c4bd75e825c07a5760f3260911c7c *tests/testthat/test-xml_children.R 1691ae6baa7dae037db77f8dff805305 *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 fdb983f74645bb473ad6cd64fd4cd8de *vignettes/modification.Rmd 4b198a3f236c08d15f90d8a66a08bd04 *vignettes/releases/xml2-1.1.1.Rmd ���������������������������������������������������������������������������������������xml2/inst/������������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�14151212034�012102� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/inst/doc/��������������������������������������������������������������������������������������0000755�0001762�0000144�00000000000�14151212034�012647� 5����������������������������������������������������������������������������������������������������ustar �ligges��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xml2/inst/doc/modification.R������������������������������������������������������������������������0000644�0001762�0000144�00000006000�14151212033�015432� 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�00000011757�14151211500�015770� 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 https://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�00000115775�14151212034�016222� 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="2021-11-29" /> <title>Node Modification

Node Modification

Jim Hester

2021-11-29

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  595099 31.8    1330608 71.1         NA  1328667 71.0
#> Vcells 1100424  8.4    8388608 64.0      32768  2028747 15.5

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  595152 31.8    1330608 71.1         NA  1328667 71.0
#> Vcells 1100481  8.4    8388608 64.0      32768  2028747 15.5

Namespaces

We want to construct a document with the following namespace layout. (From https://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/0000755000176200001440000000000014147164673013551 5ustar liggesusersxml2/inst/include/xml2_types.h0000644000176200001440000000327614147164673016040 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); R_PreserveObject(data_); } XPtr(const XPtr &old) { data_ = old.data_; R_PreserveObject(data_); } XPtr& operator=(const XPtr &other) { R_PreserveObject(other.data_); if (data_ != NULL) { R_ReleaseObject(data_); } data_ = other.data_; return *this; } 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/cleanup0000755000176200001440000000003514151212037012503 0ustar liggesusers#!/bin/sh rm -f src/Makevars xml2/configure0000755000176200001440000000655114151212037013046 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 # Fix a missing libxml2 directory on the requested include directory # https://github.com/r-lib/xml2/issues/296 if [ "${OS_TYPE}" = "Darwin" ] && echo "${PKGCONFIG_CFLAGS}" | grep -sq "/usr/include$"; then PKGCONFIG_CFLAGS="$PKGCONFIG_CFLAGS/libxml2" 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