R Under development (unstable) (2026-02-03 r89375 ucrt) -- "Unsuffered Consequences"
Copyright (C) 2026 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> library(XML)
>
> # Changed after 3.99-0.16.1: replaced the use of xmlKeepBlanksDefault()
> # with the NOBLANKS parser option. The output must stay the same.
> for (trim in c(TRUE, FALSE)) for (useInternalNodes in c(TRUE, FALSE))
+ print(
+ xmlValue(
+ xmlChildren(
+ xmlRoot(
+ xmlTreeParse(
+ system.file(
+ 'extdata/keep_blanks.xml',
+ package = 'XML'
+ ),
+ trim = trim,
+ useInternalNodes = useInternalNodes
+ )
+ )
+ )[[1+!trim]]
+ )
+ )
[1] "\n Depending on the \"trim\" option, blanks before and after this\n sentence may be stripped.\n "
[1] "Depending on the \"trim\" option, blanks before and after this\n sentence may be stripped."
[1] "\n Depending on the \"trim\" option, blanks before and after this\n sentence may be stripped.\n "
[1] "\n Depending on the \"trim\" option, blanks before and after this\n sentence may be stripped.\n "
> for (trim in c(TRUE, FALSE)) print(
+ getNodeSet(
+ xmlRoot(htmlParse(
+ '
Bar
',
+ asText = TRUE, trim = trim
+ )),
+ '//text()'
+ )
+ )
[[1]]
Bar
attr(,"class")
[1] "XMLNodeSet"
[[1]]
Bar
[[2]]
attr(,"class")
[1] "XMLNodeSet"
>
> # Changed after 3.99-0.16.1: replaced the use of
> # xmlSubstituteEntitiesDefault() with the NOENT parser option.
> # Documentation says that `replaceEntities` affects the internals, not
> # the output (which stays the same).
> for (replaceEntities in c(TRUE, FALSE)) print(
+ xmlValue(
+ xmlChildren(xmlRoot(
+ xmlTreeParse(
+ system.file(
+ 'extdata/substitute_entities.xml',
+ package = 'XML'
+ ),
+ replaceEntities = replaceEntities
+ )
+ ))[[1]]
+ )
+ )
[1] "performed substitution"
[1] "performed substitution"
>
> # Changed after 3.99-0.16.1: The use of xmlParseMarkupDecl and
> # xmlSkipBlankChars is now deprecated. Use more similar code paths for
> # reading the DTD from file vs. a string instead.
> sortnames <- function(l) l[sort(names(l))]
>
> dtdFile <- system.file("exampleData", "foo.dtd", package = "XML")
> dtd_from_file <- lapply(suppressWarnings(parseDTD(dtdFile)), sortnames)
>
> txt <- paste(readLines(dtdFile), collapse = "\n")
> dtd_from_text <- lapply(suppressWarnings(parseDTD(txt, asText = TRUE)), sortnames)
>
> all.equal(dtd_from_file, dtd_from_text)
[1] TRUE
> str(dtd_from_text, 2)
List of 2
$ elements:List of 10
..$ dataset :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ entry :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ entry0 :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ entry1 :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ entry2 :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ entry3 :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ record :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ tmp :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ variable :List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
..$ variables:List of 4
.. ..- attr(*, "class")= chr "XMLElementDef"
$ entities:List of 2
..$ foobar :List of 3
.. ..- attr(*, "class")= chr "XMLEntity"
..$ outside:List of 3
.. ..- attr(*, "class")= chr "XMLSystemEntity"
>
> # saveXML() for class 'HTMLInternalDocument': the 'indent' argument
> # hasn't been working for a while and nobody seemed to notice
> html <- htmlParse(
+ 'wat
',
+ asText = TRUE, useInternalNodes = TRUE
+ )
> stopifnot(is(html, 'HTMLInternalDocument'))
> # calls RS_XML_dumpHTMLDoc()
> cat(saveXML(html, indent = TRUE))
wat
> cat(saveXML(html, indent = FALSE))
wat
> rm(html)
>
> xml <- xmlParse(
+ '',
+ asText = TRUE, useInternalNodes = TRUE
+ )
> stopifnot(is(xml, 'XMLInternalDocument'))
> # calls R_saveXMLDOM
> cat(saveXML(xml, indent = TRUE))
> cat(saveXML(xml, indent = FALSE))
> root <- xmlRoot(xml)
> stopifnot(is(root, 'XMLInternalNode'))
> # calls RS_XML_printXMLNode
> cat(saveXML(root, indent = TRUE), '\n')
> cat(saveXML(root, indent = FALSE), '\n')
> rm(xml, root)
>
> # Changed after 3.99-0.20: replaced the use of ctx->replaceEntities with
> # the NOENT parser option.
> for (replaceEntities in c(TRUE, FALSE)) {
+ e <- new.env(parent = emptyenv())
+ handlers <- list(
+ entityDeclaration = function(key, foo, value, ...) assign(key, value, e),
+ getEntity = function(key) get(key, e),
+ text = print
+ )
+ xmlEventParse(
+ system.file(
+ 'extdata/substitute_entities.xml',
+ package = 'XML'
+ ),
+ replaceEntities = replaceEntities,
+ handlers = handlers
+ )
+ }
[1] "performed substitution"
[1] "performed substitution"
>
> proc.time()
user system elapsed
0.32 0.07 0.40