File: xml_children.R

package info (click to toggle)
r-cran-xml2 1.1.0-1~bpo8%2B1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 852 kB
  • sloc: cpp: 1,057; xml: 115; sh: 53; ansic: 12; makefile: 6
file content (141 lines) | stat: -rw-r--r-- 3,517 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#' Navigate around the family tree.
#'
#' \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.
#'
#' @inheritParams xml_name
#' @param only_elements For \code{xml_length}, should it count all children,
#'   or just children that are elements (the default)?
#' @param 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
#' @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, node_children)
}

#' @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, node_children, onlyNode = FALSE)
}

#' @export
#' @rdname xml_children
xml_parents <- function(x) {
  nodeset_apply(x, node_parents)
}

#' @export
#' @rdname xml_children
xml_siblings <- function(x) {
  nodeset_apply(x, node_siblings)
}

#' @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(node_parent(x$node), x$doc)
}

#' @export
xml_parent.xml_nodeset <- function(x) {
  nodeset_apply(x, node_parent)
}


#' @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) {
  node_length(x$node, onlyNode = 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 (!doc_has_root(x$doc)) {
    xml_missing()
  } else {
    xml_document(x$doc)
  }
}