I'm trying to create a POST request, but the body parameter isn't working as I expected.
The POST_bodyRequest.xml file
<?xml version="1.0" encoding="UTF-8"?>
<rs:alarm-request throttlesize="0"
xmlns:rs="http://www.ca.com/spectrum/restful/schema/request"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.ca.com/spectrum/restful/schema/request ../../../xsd/Request.xsd ">
<rs:requested-attribute id="0x10000"/>
<rs:requested-attribute id="0x10001"/>
<rs:requested-attribute id="0x10009"/>
<rs:requested-attribute id="0x1000a"/>
<rs:requested-attribute id="0x1006e"/>
<rs:requested-attribute id="0x11ee8"/>
</rs:alarm-request>
The code, basically the POST call
xml <- upload_file("POST_bodyRequest.xml")
r2 <- POST(url, login.password, body = list(xml))
status_code(r2)
First thing to note is that the content from the file isn't saved in "xml" file:
> xml <- upload_file("POST_bodyRequest.xml")
> xml
Form file: POST_bodyRequest.xml (type: application/xml)
> str(xml)
List of 2
$ path: chr "D:\\MPM\\POST_bodyRequest.xml"
$ type: chr "application/xml"
- attr(*, "class")= chr "form_file"
Therefore, the POST call returns an error
> r2 <- POST(url, login.password, body = list(xml))
Error: All components of body must be named
> status_code(r2)
[1] 415
I've also tried do read the xml file using xmlParse(). In this case, the code is recovered as expected, but I get the same error when calling POST.
> xml <- xmlParse(file = "POST_bodyRequest.xml")
> r2 <- POST(url, autenticacao, body = list(xml))
Erro: All components of body must be named
> xml
<?xml version="1.0" encoding="UTF-8"?>
<rs:alarm-request xmlns:rs="http://www.ca.com/spectrum/restful/schema/request" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throttlesize="0" xsi:schemaLocation="http://www.ca.com/spectrum/restful/schema/request ../../../xsd/Request.xsd ">
<rs:requested-attribute id="0x10000"/>
<rs:requested-attribute id="0x10001"/>
<rs:requested-attribute id="0x10009"/>
<rs:requested-attribute id="0x1000a"/>
<rs:requested-attribute id="0x1006e"/>
<rs:requested-attribute id="0x11ee8"/>
</rs:alarm-request>
> str(list(xml))
List of 1
$ :Classes 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr>
> status_code(r2)
[1] 415
I had no trouble with GET requests in R. The POST request works fine with SoapUI. So, what am I doing wrong?
Well, it did work. The problem wasn't anything related to the upload_file() function or the xml file. It was the url variable, which wasn't updated to the POST version. I'd like to thank for the confirmations and check this issue as resolved.
Related
I have an xml response containing Body and Header nodes, how can I access the value of the $Envelope$Body$checkVatResponse$valid node?
For some reason I already can't find the Body using xml_find_all
library(httr)
library(dplyr)
library(rvest)
library(xml2)
body = r'[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" >
<soapenv:Header/>
<soapenv:Body>
<urn:checkVat xmlns:urn="urn:ec.europa.eu:taxud:vies:services:checkVat:types">
<urn:countryCode>NL</urn:countryCode>
<urn:vatNumber>800938495B01</urn:vatNumber>
</urn:checkVat>
</soapenv:Body>
</soapenv:Envelope>]'
r <- POST("http://ec.europa.eu/taxation_customs/vies/services/checkVatTestService", body = body)
stop_for_status(r)
content(r) %>% xml_find_all('//Body')
content(r) %>% xml2::as_list()
res <- content(r)
xml_children(res) %>% xml_name()
# [1] "Header" "Body"
xml_find_all(res,'.//Body')
# {xml_nodeset (0)}
When working with XML data, you need to be mindful of the namespaces used in the file. You need to previx namespaced nodes with the correct namespace. To extract the valid value you can use
content(r) %>% xml_find_all('//env:Body/ns2:checkVatResponse/ns2:valid')
To see all the namespaces used by the file you can run
content(r) %>% xml_ns()
# env <-> http://schemas.xmlsoap.org/soap/envelope/
# ns2 <-> urn:ec.europa.eu:taxud:vies:services:checkVat:types
Problem
I have an XML file that I would like to parse in R. I know that this file is not corrupted because the following Python code seems to work:
>>> import xml.etree.ElementTree as ET
>>> xml_tree = ET.parse(PATH_TO_MY_XML_FILE)
>>> do_my_regular_xml_stuff_that_seems_to_work_no_problem(xml_tree)
Now, when I try to run the following code in R, I get an error message:
> library("XML")
> xml_tree <- XML::xmlParse(PATH_TO_MY_XML_FILE)
Error in nchar(text_repr): invalid multibyte string, element 1
Traceback:
Alright, maybe the parser doesn't recognize the encoding. Luckily this should be specified in a decent XML file. So, I go to my shell and check:
$ head -n1 PATH_TO_MY_XML_FILE
??<?xml version="1.0" encoding="utf-16"?>
Now, I can go back to R and explicitly pass on the encoding, only to face the next error message where I got stuck now:
> library("XML")
> xml_tree <- XML::xmlParse(PATH_TO_MY_XML_FILE, encoding='UTF-16')
Start tag expected, '<' not found
Error: 1: Start tag expected, '<' not found
Traceback:
1. XML::xmlParse(filePath, encoding = "UTF-16")
2. (function (msg, ...)
. {
. if (length(grep("\\\n$", msg)) == 0)
. paste(msg, "\n", sep = "")
. if (immediate)
. cat(msg)
. if (length(msg) == 0) {
. e = simpleError(paste(1:length(messages), messages, sep = ": ",
. collapse = ""))
. class(e) = c(class, class(e))
. stop(e)
. }
. messages <<- c(messages, msg)
. })(character(0))
A last attempt to check (in R) if the file is in fact "UTF-16" encoded yields:
> f <- file(filePath, 'r', encoding = "UTF-16")
> firstLine <- readLines(f, n=1)
> close(f)
> print(line)
[1] "<?xml version=\"1.0\" encoding=\"utf-16\"?>"
Which looks just about right to me.
Question(s)
Does anyone know what is happening here? Is this a bug from the XML library? Is the file maybe not 'UTF-16' encoded, even though it claims it is? What are the two question marks ?? that I see when I print the file into the shell? These question marks don't appear when reading in the file properly...
Is this a bug from the XML library?
I think there could be a bug here. If I generate a valid UTF-16 XML document, which will have an initial byte-order mark:
$ echo '<a>😊</a>' | iconv -t utf-16 >a-utf16.xml
$ xxd a-utf16.xml
00000000: fffe 3c00 6100 3e00 3dd8 0ade 3c00 2f00 ..<.a.>.=...<./.
00000010: 6100 3e00 0a00 a.>...
then I can parse it with:
> XML::xmlParse('a-utf16.xml')
<?xml version="1.0"?>
<a>😊</a>
but not if I specify the encoding:
> XML::xmlParse('a-utf16.xml', encoding='utf-16')
Start tag expected, '<' not found
Error: 1: Start tag expected, '<' not found
Your original problem was when you weren't specifying the encoding. However:
I know that this file is not corrupted because the following Python code seems to work
That's a good hint, but I think you'll find edge cases where that doesn't hold. Try iconv for a second opinion on whether the file is encoded correctly.
For a more specific response, you'll need to post a reproducible XML file,
I am a newbie in XML and R and would like to ask you for a help. I need to extract data from XML into a dataframe in R. The XML file is following:
<?xml version="1.0" encoding="UTF-8"?>
-<Report xmlns="Tlg_Table_Begin_Ende_ValueIds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" txtHeader="Table" Name="Tlg_Table_Begin_Ende_ValueIds" xsi:schemaLocation="Tlg_Table_Begin_Ende_ValueIds http://nwlph01/ReportServer_HISTORIAN?%2FTemplates%2FPublic%2FTags%2FTlg_Table_Begin_Ende_ValueIds&rs%3AFormat=XML&rc%3ASchema=True">
-<table1 textbox7="Flags" textbox6="Quality" textbox5="Value" textbox4="Timestamp" textbox2="Tag name">
-<Detail_Collection>
<Detail Flags="8392704" Quality="128" TimeStamp2="3758.203125 " TimeStamp="3/13/2019 3:15:00 PM 3/13/2019 3:15:00 PM" TagName="SystemArchive\0101___FIT101G/UM.PV_Out#Value"/>
<Detail Flags="8392704" Quality="128" TimeStamp2="3771.9267578125 " TimeStamp="3/13/2019 3:15:01 PM 3/13/2019 3:15:01 PM" TagName="SystemArchive\0101___FIT101G/UM.PV_Out#Value"/>
<Detail Flags="8392704" Quality="128" TimeStamp2="3783.43823242188 " TimeStamp="3/13/2019 3:15:02 PM 3/13/2019 3:15:02 PM" TagName="SystemArchive\0101___FIT101G/UM.PV_Out#Value"/>
</Detail_Collection>
</table1>
</Report>
I am using following codes:
library("xml2")
df <- read_xml("lh_01.xml")
But what I receive is:
Warning message:
In doc_parse_file(con, encoding = encoding, as_html = as_html, options = options) :
xmlns: URI Tlg_Table_Begin_Ende_ValueIds is not absolute [100]
Do you have any idea what am I suppose to do?
Thank you in advance.
Searching Stackoverflow delivers e.g the folloeing URI is not absolute error - sorry I am not an XML expert what the error in your specific case may be; my know-how only goes so far as to find your xmlns URI unusual.
I am trying to parse this xml and place it on data frame form:
file content looks like this:
<?xml version="1.0" encoding="utf-8" ?>
- <dashboardreport name="Incident_Rules" version="7.2.5.1022" reportdate="2019-02-20T14:45:57.352-05:00" description="">
- <source name="app1">
- <filters summary="last 30 minutes (auto)">
<filter>tf:DiagnoseTimeframe?1550690157352:1550691957352</filter>
</filters>
</source>
- <reportheader>
- <reportdetails>
<user>user1</user>
</reportdetails>
</reportheader>
- <data>
- <incidentchartdashlet name="Incident Chart" description="">
- <incidentchartrecords structuretype="tree">
<incidentchartrecord rule="Database Exception" systemprofile="app1" />
<incidentchartrecord rule="Response time greater than 30 minutes" systemprofile="app1" />
<incidentchartrecord rule="JVM Heap Utilization > 90%" systemprofile="app1" />
</incidentchartrecords>
</incidentchartdashlet>
</data>
</dashboardreport>
The data frame needs to be like this:
Source Name Rule
App1 Database Exception
App1 Response time greater than 30 minutes
App1 JVM Heap Utilization > 90%
Need to extract "Source name" and "incidentchartrecord rule". I have tried something like this:
library("XML")
doc <- read_xml(file)
dat<-xml_find_all(doc, ".//incidentchartrecord") %>%
map_df(function(x) {
xml_find_all(x, ".//incidentchartrecord") %>%
map_df(~as.list(xml_attrs(.))) %>%
select(rule) %>%
mutate(node=xml_attr(x, "incidentchartrecord"))
})
Any ideas?
Here's an approach that works. I used xml2, instead; that's where the xml_find_all & xml_attr functions are found.
library(xml2)
doc <- read_xml("test.xml")
source <- xml_attr(xml_find_all(doc,".//source"), "name")
rules <- xml_attr(xml_find_all(doc, ".//incidentchartrecord"), "rule")
df <- data.frame("Source.Name" = source, Rule=rules, stringsAsFactors=F)
I built a web service in C# web application. I'm returning list of objects as a web service result. I need to know how to read that list of items one by one in a loop.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<checkAvailabilityResponse xmlns="http://tempuri.org/">
<checkAvailabilityResult>
<Shedule>
<Sid>int</Sid>
<Fid>int</Fid>
<FromLocation>string</FromLocation>
<FromTime>dateTime</FromTime>
<ToLocation>string</ToLocation>
<ToTime>dateTime</ToTime>
<PriceSeatA>double</PriceSeatA>
<PriceSeatB>double</PriceSeatB>
<PriceSeatC>double</PriceSeatC>
</Shedule>
<Shedule>
<Sid>int</Sid>
<Fid>int</Fid>
<FromLocation>string</FromLocation>
<FromTime>dateTime</FromTime>
<ToLocation>string</ToLocation>
<ToTime>dateTime</ToTime>
<PriceSeatA>double</PriceSeatA>
<PriceSeatB>double</PriceSeatB>
<PriceSeatC>double</PriceSeatC>
</Shedule>
</checkAvailabilityResult>
</checkAvailabilityResponse>
</soap:Body>
</soap:Envelope>
This is the way I tried:
SriLankanWebService.Service1SoapClient air1 = new AgentPortal.SriLankanWebService.Service1SoapClient();
List<Shedule> air1Response = (List<Shedule>)air1.checkAvailability(drpFrom.SelectedValue.ToString(), drpTo.SelectedValue.ToString(), DateTime.Parse(txtDepartOn.Text));
When I tried it says:
Error 1 Cannot implicitly convert type 'AgentPortal.SriLankanWebService.Shedule[]' to 'System.Collections.Generic.List<AgentPortal.Shedule>' D:\DCBSD\AgentPortal\AgentPortal\Home.aspx.cs 32 46 AgentPortal
I need to use it in a loop.
Please update your code in last line from above code from:
List<Shedule> air1Response = (List<Shedule>)air1.checkAvailability(drpFrom.SelectedValue.ToString(), drpTo.SelectedValue.ToString(), DateTime.Parse(txtDepartOn.Text));
to
AgentPortal.SriLankanWebService.Shedule[] = air1.checkAvailability(drpFrom.SelectedValue.ToString(), drpTo.SelectedValue.ToString(), DateTime.Parse(txtDepartOn.Text));
That will fix the issue.