Using XML Tags to Structure Output
So far you've used XML tags to structure what goes into Claude. In this lesson you'll use them to control what comes out. Requesting XML-structured output is one of the most powerful techniques for building reliable Claude-powered applications, because structured output can be parsed deterministically, validated programmatically, and integrated into data pipelines without brittle string manipulation.
Why XML Output Beats Prose for Programmatic Use
When you ask Claude for information in plain prose, parsing the response requires making assumptions. Is the answer in the first paragraph or the last? Does "the confidence is high" mean 0.9 or 0.7? If the format changes slightly between calls, your parser breaks.
When you ask Claude to output XML, you get:
- Predictable structure: Tags are in the positions you specified
- Machine-parseable content: Standard XML parsers handle it reliably
- Explicit field boundaries: No ambiguity about where one value ends and another begins
- Null handling: Missing fields can be represented as empty tags (
<field></field>) - Nested data: Complex hierarchies that would require multiple regex patterns in prose can be expressed naturally
This doesn't mean XML is always the right output format — JSON is often preferable for JavaScript applications, and plain text is better for human-facing outputs. But XML is a strong choice when you need Claude to reason through a problem and produce structured output, because it fits Claude's training and doesn't require the additional step of converting reasoning to JSON syntax.
Common Output Tag Patterns
The reasoning + answer pattern
This is the most broadly useful pattern. Ask Claude to show its work in <reasoning> tags, then give the final answer in <answer> tags. This lets you optionally display the reasoning to users, log it for debugging, or strip it and use only the answer.
<instructions>
Analyze the following customer review and determine the overall sentiment.
Respond using this exact structure:
<reasoning>
[Walk through the key signals in the review that indicate sentiment]
</reasoning>
<answer>positive | negative | mixed | neutral</answer>
<confidence>0.0 to 1.0</confidence>
</instructions>
The result + metadata pattern
For tasks where the main output has accompanying metadata:
<instructions>
Translate the following text to French.
Respond in this structure:
<result>[translated text]</result>
<notes>[any translation decisions worth flagging, or "none"]</notes>
<formality>formal | informal | neutral</formality>
</instructions>
The multi-field extraction pattern
For extracting structured data from unstructured text:
<instructions>
Extract the key information from this job posting.
Output only this XML structure, no other text:
<job>
<title>[job title]</title>
<company>[company name]</company>
<location>[city, state or "Remote"]</location>
<salary_min>[number or "not specified"]</salary_min>
<salary_max>[number or "not specified"]</salary_max>
<required_years_experience>[number or "not specified"]</required_years_experience>
<remote_ok>[true | false | hybrid]</remote_ok>
<key_requirements>
<requirement>[requirement 1]</requirement>
<requirement>[requirement 2]</requirement>
</key_requirements>
</job>
</instructions>
Requesting Structured Output: Key Techniques
1. Show the structure explicitly in the prompt
Don't just describe the structure — show it. Include the XML tags with placeholder text:
Respond using exactly this structure:
<analysis>
<sentiment>positive | negative | mixed</sentiment>
<confidence>0.0 to 1.0</confidence>
<key_evidence>[one sentence]</key_evidence>
</analysis>
2. Use "output only" instructions to prevent prose wrapping
By default, Claude often adds preamble like "Here is my analysis:" before structured output. Suppress this:
Output ONLY the XML structure below. Do not include any text before or after the XML tags.
3. Specify what to do with missing information
Define how Claude should handle fields it can't fill:
If a field cannot be determined from the input, use "unknown" as the value.
Do not omit tags — always include every field in the structure.
4. Use XML comments to annotate the schema in the prompt
For complex structures, annotate the schema inline:
<extraction>
<entity_name>[full legal name]</entity_name>
<entity_type>[individual | organization | government]</entity_type>
<risk_score>[integer 1-10, where 10 is highest risk]</risk_score>
<risk_factors>
<!-- Include one <factor> tag per identified risk factor, minimum 1, maximum 5 -->
<factor>[risk factor description]</factor>
</risk_factors>
</extraction>
Live Examples: Requesting Structured Output
Here's a prompt requesting structured sentiment analysis with reasoning:
Try modifying the instructions to add a <summary> tag for a one-sentence summary, or to extract a <price_sensitivity> field.
Parsing XML Responses Programmatically
Once Claude returns XML, parsing it is straightforward with any XML library.
Python (using ElementTree):
import xml.etree.ElementTree as ET
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=1024,
messages=[{
"role": "user",
"content": your_structured_prompt
}]
)
xml_text = response.content[0].text
# Parse the XML
root = ET.fromstring(xml_text)
sentiment = root.find("overall_sentiment").text
confidence = float(root.find("confidence").text)
reasoning = root.find("reasoning").text
# Extract nested elements
aspects = []
for aspect in root.findall(".//aspect"):
aspects.append({
"name": aspect.find("name").text,
"sentiment": aspect.find("sentiment").text,
"quote": aspect.find("quote").text
})
JavaScript (using DOMParser):
const parser = new DOMParser();
const doc = parser.parseFromString(xmlText, "text/xml");
const sentiment = doc.querySelector("overall_sentiment").textContent;
const confidence = parseFloat(doc.querySelector("confidence").textContent);
const aspects = [...doc.querySelectorAll("aspect")].map(aspect => ({
name: aspect.querySelector("name").textContent,
sentiment: aspect.querySelector("sentiment").textContent,
quote: aspect.querySelector("quote").textContent
}));
Important: Always wrap XML parsing in try/catch. Claude will almost always produce valid XML when instructed to, but network interruptions, max token limits, or edge cases in the input can produce malformed output. Build defensive parsing.
Combining XML Output with JSON: Hybrid Structures
Sometimes you want the benefits of XML for Claude's reasoning process but need JSON for downstream consumption. Two approaches:
Option 1: Ask Claude to output JSON inside XML thinking tags
<instructions>
Analyze this support ticket and classify it.
First, show your reasoning in <thinking> tags.
Then output the final classification as a JSON object inside <result> tags.
</instructions>
Response structure:
<thinking>
The customer mentions billing twice and references an invoice number, so this is clearly a billing issue...
</thinking>
<result>
{"category": "billing", "priority": "P2", "sentiment": "frustrated", "action_required": true}
</result>
You parse <result> content as JSON after extracting it from the XML wrapper.
Option 2: Request JSON with embedded XML for rich text fields
Less common, but useful when you need machine-readable structure for most fields but rich formatted content for others (like a long explanation):
{
"category": "billing",
"explanation": "<p>The customer is disputing invoice #4821...</p>",
"priority": 2
}
The embedded XML/HTML in string fields is rendered separately.
Output Tag Best Practices
Name tags for their semantic role, not their data type:
- Good:
<confidence>,<reasoning>,<recommendation> - Less good:
<string1>,<value>,<field3>
Be explicit about value constraints:
<priority>1 | 2 | 3 | 4 | 5 (1 = critical, 5 = low)</priority>
<confidence>float between 0.0 and 1.0</confidence>
Define collection patterns:
<tags>
<!-- Include one <tag> per relevant tag, 1-5 total -->
<tag>[tag value]</tag>
</tags>
Use attributes for metadata, text content for values:
<score type="nps" scale="0-10">8</score>
<entity type="person" confidence="0.94">Sarah Chen</entity>
Exercise: Design a Structured Output Prompt
Key Takeaways
- Requesting XML output makes Claude responses machine-parseable, predictable, and integrable into data pipelines without brittle string matching
- The core patterns are: reasoning + answer, result + metadata, and multi-field extraction
- Always show the exact output structure in your prompt — don't just describe it, model it with placeholder text
- Use "output ONLY the XML structure" instructions to prevent prose wrapping
- Define how Claude should handle missing fields: use a consistent sentinel value like "unknown" or "none" rather than omitting tags
- XML output pairs well with JSON: use XML for Claude's reasoning, extract and parse JSON from within the result tags
- Parse defensively: wrap XML parsing in try/catch and build fallback handling for malformed responses
Discussion
Sign in to join the discussion.

