About this lesson
REST Assured: parse an XML response and read product fields with XmlPath
Learn REST AssuredAdvancedXML Responses
How it works
The /xml/products endpoint lists five products, one <product> element each, with id, name, price, category and inStock children. Compare that with the JSON product at /products/1, where category is an object holding its own id and name. In this XML feed the category is a plain text element. The structures look similar but are not interchangeable, and a path copied from a JSON test will not find anything here.
Every XML value is text until you say otherwise. get() and getString() on the price both return the String "1299.99", and get() on a stock flag returns "false" as a String too. The typed getters convert: getDouble() yields a Double of 1299.99, and getBoolean() on the fourth product's flag yields false. Interesting detail for anyone switching formats: JsonPath returns a Float for that same price in JSON, while XmlPath gives a Double when asked.
Validation in XML is mostly about reaching the right element and comparing it as the right type. GPath closures make that easier on a list: findAll with a condition on category filters the products, and adding .name after it collects just their names, which getList() returns as a Java list.
About the assignment
Request the XML product catalogue and print the first product's name and its category, each after a label.
What you will do
- Send a GET for
/xml/productsand callxmlPath()on the response. - Read the first product's name with
getString()and the root-first path shown in the starter comment. - Read its category from the same element. It is a direct child that holds text, so the path ends at
categorywith nothing after it. - Print a
Product:line with the name and aCategory:line with the category.
Common mistakes
Carrying over the JSON path
In JSON you would write
category.name. Here that path points at an element that does not exist, and XmlPath returns an empty string instead of failing, so the output simply shows a blank category.Casting get() to a number
Assigning the result of
get()on the price to aDoublevariable compiles, then throwsClassCastExceptionat runtime because the value is a String. CallgetDouble()when you need a number.Relying on element order
Index zero is the first product today. If the feed is ever sorted differently, the test reads another item. For checks that matter, locate the element by content with a
findclosure, then read the field you want.
In a real test suite
XML product and pricing feeds are common in retail integrations, and tests against them usually check a handful of business rules: prices parse as positive numbers, every product has a category, flags are real booleans. A JUnit 5 test can read the whole name list with getList() and assert on it with Hamcrest hasItems(), then spot-check one element by content.
Related lessons
- Extract from XML with XmlPathIntroduces XmlPath and the root-first GPath style on the XML user list.
- Nested POJO DeserializationMaps the JSON product, nested category object included, onto Java classes.
- Content NegotiationAsks one endpoint for JSON or XML through the
Acceptheader.
To try one of these calls on any API endpoint without a task, open the Online Selenium Java Compiler (REST Assured is included).
Starter code
The editor above opens with this code. Fill in the TODO lines, then run and submit it.
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import io.restassured.path.xml.XmlPath;
import static io.restassured.RestAssured.*;
public class Main {
public static void main(String[] args) {
RestAssured.baseURI = "https://testkru.com/api";
// TODO: GET /xml/products
// TODO: Extract first product's name and category using XmlPath
// Path: "products.product[0].name" and "products.product[0].category"
}
}