在R语言中通过httr包获取XML并转换为DataFrame的方法
Got it, let's break down how to take that XML response from your httr POST request and turn it into a clean DataFrame. I'll use xml2 for parsing XML (it's intuitive and plays well with tidyverse tools) and dplyr/purrr for wrangling the data into shape.
Step 1: Install & Load Required Packages
First, make sure you have these packages installed (if not, run the install commands):
# Install packages if needed install.packages(c("httr", "xml2", "dplyr", "purrr")) # Load them library(httr) library(xml2) library(dplyr) library(purrr)
Step 2: Parse the XML Response
Assuming you already sent your POST request and have the response stored in an object called resp, we'll parse it into an XML document:
# Send POST request (replace with your actual URL and body) resp <- POST( url = "your-api-endpoint-url", body = list(your_parameters_here), encode = "form" # adjust encode type based on your API requirements ) # Parse the response into an XML document xml_doc <- content(resp, as = "parsed", type = "application/xml")
Step 3: Extract Terminal Metadata & Report Data
Your XML structure has a Terminal node with attributes (isn, imo, name) and a nested Report node with the actual data points. We'll extract both and combine them:
# Get all Terminal nodes (handles multiple Terminals if present) terminal_nodes <- xml_find_all(xml_doc, ".//Terminal") # Process each Terminal into a row (or rows if multiple Reports per Terminal) df <- map_dfr(terminal_nodes, function(terminal) { # Extract Terminal attributes terminal_meta <- tibble( isn = xml_attr(terminal, "isn"), imo = xml_attr(terminal, "imo"), vessel_name = xml_attr(terminal, "name") ) # Get all Report nodes inside this Terminal report_nodes <- xml_find_all(terminal, ".//Report") # Extract Report data report_data <- map_dfr(report_nodes, function(report) { tibble( datetime = xml_text(xml_find_first(report, ".//DateTime")), lat = as.numeric(xml_text(xml_find_first(report, ".//Lat"))), lon = as.numeric(xml_text(xml_find_first(report, ".//Lon"))), cog = as.integer(xml_text(xml_find_first(report, ".//Cog"))), sog = as.integer(xml_text(xml_find_first(report, ".//Sog"))), voltage = as.integer(xml_text(xml_find_first(report, ".//Voltage"))), status = xml_text(xml_find_first(report, ".//Status")) # Add more fields here if your Report has additional nodes ) }) # Combine Terminal metadata with Report data bind_cols(terminal_meta, report_data) })
Step 4: Clean Up Data Types (Optional but Recommended)
Convert the datetime field to a proper POSIXct datetime object for easier analysis:
df <- df %>% mutate(datetime = as.POSIXct(datetime, format = "%d/%m/%Y %H:%M:%S"))
How This Works
xml_find_alllocates all matching nodes in the XML documentxml_attrpulls attribute values from a node (like theisnon Terminal)xml_textextracts the text content from a node (like the DateTime value)map_dfrapplies a function to each node and binds the results into a single DataFrame (perfect for handling multiple Terminals or Reports)
This solution is flexible: if your XML has multiple Terminal nodes or multiple Report nodes per Terminal, it will still work and create a row for each unique Terminal-Report combination.
内容的提问来源于stack exchange,提问作者Dhiraj

