Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error on creating new XML - Expecting an external pointer #239

Closed
douglaszickuhr opened this issue Nov 6, 2018 · 4 comments
Labels
bug

Comments

@douglaszickuhr
Copy link

@douglaszickuhr douglaszickuhr commented Nov 6, 2018

Issue Description and Expected Result

When trying to create a new XML body and it has a namespace defined on the root node, xml2 returns an error, even that the namespaces are correctly assigned. It just happens with the root node. An example of a situation like that is a SOAP request XML. The root node will be called soap:Envelope for soap 1.1 or soap12:for soap 1.2.

Reproducible Example

library(magrittr)
#> Warning: package 'magrittr' was built under R version 3.5.1
library(xml2)
#> Warning: package 'xml2' was built under R version 3.5.1

soap_body_xml <- function(){
  body <- xml_new_root( .value = "soap12:Envelope",
                        "xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance",
                        "xmlns:xsd" = "http://www.w3.org/2001/XMLSchema",
                        "xmlns:soap12" = "http://www.w3.org/2003/05/soap-envelope") %>%
    xml_add_child("soap12:Body")
  
  body
}

soap_body_xml() %>%
  xml_root()
#> Error in ns_lookup(parent$doc, parent$node, parts[[1]]): Expecting an external pointer: [type=NULL].

Created on 2018-11-06 by the reprex package (v0.2.1)

-->

Session Info
devtools::session_info() # Paste output below
#> output
- Session info --------------------------------------------------------------------------------------------------------------------------------------
 setting  value                       
 version  R version 3.5.0 (2018-04-23)
 os       Windows 7 x64 SP 1          
 system   x86_64, mingw32             
 ui       RStudio                     
 language (EN)                        
 collate  English_Ireland.1252        
 ctype    English_Ireland.1252        
 tz       Europe/London               
 date     2018-11-06                  

- Packages ------------------------------------------------------------------------------------------------------------------------------------------
 package     * version date       lib source        
 assertthat    0.2.0   2017-04-11 [1] CRAN (R 3.5.1)
 backports     1.1.2   2017-12-13 [1] CRAN (R 3.5.0)
 base64enc     0.1-3   2015-07-28 [1] CRAN (R 3.5.0)
 callr         3.0.0   2018-08-24 [1] CRAN (R 3.5.1)
 cli           1.0.1   2018-09-25 [1] CRAN (R 3.5.1)
 clipr         0.4.1   2018-06-23 [1] CRAN (R 3.5.1)
 crayon        1.3.4   2017-09-16 [1] CRAN (R 3.5.1)
 desc          1.2.0   2018-05-01 [1] CRAN (R 3.5.1)
 devtools      2.0.1   2018-10-26 [1] CRAN (R 3.5.1)
 digest        0.6.18  2018-10-10 [1] CRAN (R 3.5.1)
 evaluate      0.12    2018-10-09 [1] CRAN (R 3.5.1)
 fs            1.2.6   2018-08-23 [1] CRAN (R 3.5.1)
 glue          1.3.0   2018-07-17 [1] CRAN (R 3.5.1)
 hms           0.4.2   2018-03-10 [1] CRAN (R 3.5.1)
 htmltools     0.3.6   2017-04-28 [1] CRAN (R 3.5.1)
 httr        * 1.3.1   2017-08-20 [1] CRAN (R 3.5.1)
 janitor     * 1.1.1   2018-07-31 [1] CRAN (R 3.5.1)
 knitr         1.20    2018-02-20 [1] CRAN (R 3.5.1)
 lubridate   * 1.7.4   2018-04-11 [1] CRAN (R 3.5.1)
 magrittr    * 1.5     2014-11-22 [1] CRAN (R 3.5.1)
 memoise       1.1.0   2017-04-21 [1] CRAN (R 3.5.1)
 pillar        1.3.0   2018-07-14 [1] CRAN (R 3.5.1)
 pkgbuild      1.0.2   2018-10-16 [1] CRAN (R 3.5.1)
 pkgconfig     2.0.2   2018-08-16 [1] CRAN (R 3.5.1)
 pkgload       1.0.2   2018-10-29 [1] CRAN (R 3.5.1)
 prettyunits   1.0.2   2015-07-13 [1] CRAN (R 3.5.1)
 processx      3.2.0   2018-08-16 [1] CRAN (R 3.5.1)
 ps            1.2.0   2018-10-16 [1] CRAN (R 3.5.1)
 purrr       * 0.2.5   2018-05-29 [1] CRAN (R 3.5.1)
 R6            2.3.0   2018-10-04 [1] CRAN (R 3.5.1)
 Rcpp          0.12.19 2018-10-01 [1] CRAN (R 3.5.1)
 readr       * 1.1.1   2017-05-16 [1] CRAN (R 3.5.1)
 remotes       2.0.2   2018-10-30 [1] CRAN (R 3.5.1)
 reprex      * 0.2.1   2018-09-16 [1] CRAN (R 3.5.1)
 rlang         0.3.0.1 2018-10-25 [1] CRAN (R 3.5.1)
 rmarkdown     1.10    2018-06-11 [1] CRAN (R 3.5.1)
 rprojroot     1.3-2   2018-01-03 [1] CRAN (R 3.5.1)
 rstudioapi    0.8     2018-10-02 [1] CRAN (R 3.5.1)
 sessioninfo   1.1.0   2018-09-25 [1] CRAN (R 3.5.1)
 stringi       1.2.4   2018-07-20 [1] CRAN (R 3.5.1)
 stringr     * 1.3.1   2018-05-10 [1] CRAN (R 3.5.1)
 tibble        1.4.2   2018-01-22 [1] CRAN (R 3.5.1)
 usethis       1.4.0   2018-08-14 [1] CRAN (R 3.5.1)
 whisker       0.3-2   2013-04-28 [1] CRAN (R 3.5.1)
 withr         2.1.2   2018-03-15 [1] CRAN (R 3.5.1)
 xml2        * 1.2.0   2018-01-24 [1] CRAN (R 3.5.1)
 yaml          2.2.0   2018-07-25 [1] CRAN (R 3.5.1)

[1] C:/Users/ST9DZ1/Documents/R/win-library/3.5
[2] C:/Program Files/R/R-3.5.0/library
```r
</details>
@nuest

This comment has been minimized.

Copy link
Contributor

@nuest nuest commented Mar 27, 2019

I have the same problem creating documents with a namespace prefix on the root node. My workaround is to create a suitable string and then read that in to start with:

body <- xml2::read_xml('<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope" />')
xml2::xml_add_child(body, "soap12:Body")
body
{xml_document}
<Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
[1] <soap12:Body/>

With some pointers how to start I'd be happy to attempt a PR to fix this. My first guess it the ... have to be used in

namespace <- ns_lookup(parent$doc, parent$node, parts[[1]])
.

@douglaszickuhr

This comment has been minimized.

Copy link
Author

@douglaszickuhr douglaszickuhr commented Mar 29, 2019

Hey @nuest your solution seems way more elegant than mine. I've been creating an empty XML Body just containing a simple Body tag and later I replace it for soap12:Body using str_replace_all function from stringr package.

Anyway, it's been working here as a workaround but I'd love to contribute to fix this on xml2 package.

Cheers

soap_body_xml() %>%
      xml_add_child(method, xmlns = "http://ultraasp.net/") %>%
      xml_add_child("domain", domain) %>%
      xml_add_sibling("sessionToken", session_token) %>%
      xml_add_sibling("xmlMessage", xml_message) %>%
      xml_root() %>%
      as("character") %>%
      str_replace_all("Envelope", "soap12:Envelope") %>%
      str_replace_all("Body", "soap12:Body")
@douglaszickuhr

This comment has been minimized.

Copy link
Author

@douglaszickuhr douglaszickuhr commented Mar 29, 2019

I have gone through the code and it looks like the problem is exactly what you pointed. There is a problem when the namespace is being looked up.

My guess is that there is no point in validate that if the parent node is not a node, right? Like when creating a root node. I've tried the following solution, just adding a new condition to ignore the ns_lookup call if the parent$node is null.

What do you think? It might be too simplistic but it could fix the problem. :)

parts <- strsplit(.value, ":")[[1]]
  if ((length(parts) == 2) & !is.null(parent$node)) {
    namespace <- ns_lookup(parent$doc, parent$node, parts[[1]])
    node <- structure(list(node = node_new_ns(parts[[2]], namespace), doc = parent$doc), class = "xml_node")
  } else {
    node <- structure(list(node = node_new(.value), doc = parent$doc), class = "xml_node")
  }
@cderv

This comment has been minimized.

Copy link

@cderv cderv commented Mar 31, 2019

I know that for adding a node, you can use xml_set_namespace to set the namespace after it has been defined. See #176
However, it does not seem to work for root node , but you can use xml_name to rename the node after creation.
I would create your soap xml like this

library(magrittr)
library(xml2)

root <- xml_new_root( .value = "Envelope",
                      "xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance",
                      "xmlns:xsd" = "http://www.w3.org/2001/XMLSchema",
                      "xmlns:soap12" = "http://www.w3.org/2003/05/soap-envelope")
xml_name(root) <- "soap12:Envelope"
root %>%
  xml_add_child("Body") %>%
  xml_set_namespace("soap12") %>%
  xml_root()
#> {xml_document}
#> <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
#> [1] <soap12:Body/>

Created on 2019-03-31 by the reprex package (v0.2.1.9000)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.