> Source: https://txtfetch.com/extract/xml > Plain-text twin — every page on txtfetch.com has one. https://txtfetch.com/text --- # Markup stripped, order preserved. DITA, DocBook, JATS, XBRL filings. The content is real prose buried in tags, entities, and attributes, in document order, not alphabetical or arbitrary order. the-problem Markup formats put real content in places a simple tag-stripper doesn't look. HTML entities like ’ or & need resolving back to the character they represent, not left as literal text or double-decoded. CDATA sections hold raw, unescaped content that a naive parser can either skip entirely or fail to close correctly. XML namespaces mean the 'same' tag name can mean two different things in two different parts of a document. And in plenty of real-world XML dialects, meaningful content lives in attribute values, not just element text. Think DITA and DocBook technical docs, JATS scientific articles, or XBRL financial filings. A text-node-only extractor misses that completely. Getting this right means resolving entities. It means walking the tree in document order, rather than the order attributes happen to be declared. And it means knowing which attributes are content, versus which are just structural scaffolding. one-request-solution txtfetch parses the actual XML tree rather than regex-stripping tags. Entities resolve to their real characters, CDATA content is read correctly, and element text comes back in document order with the tag scaffolding removed. For a typed, structured view of the same document, with element names and hierarchy preserved rather than flattened to prose, request ?format=json. curl ```curl curl -X POST https://api.txtfetch.com/v1/extract \ -H "Authorization: Bearer $TXTFETCH_KEY" \ -F file=@product-catalog.xml ``` Python ```python import os import requests with open("product-catalog.xml", "rb") as f: r = requests.post( "https://api.txtfetch.com/v1/extract", headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"}, files={"file": f}, ) print(r.json()["extracted_text"]) ``` JavaScript ```javascript import { readFile } from "node:fs/promises"; const file = new Blob([await readFile("product-catalog.xml")]); const form = new FormData(); form.append("file", file, "product-catalog.xml"); const res = await fetch("https://api.txtfetch.com/v1/extract", { method: "POST", headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` }, body: form, }); const { extracted_text } = await res.json(); console.log(extracted_text); ``` Go ```go package main import ( "bytes" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "os" ) type extractResponse struct { Status string `json:"status"` ExtractedText string `json:"extracted_text"` } func main() { f, err := os.Open("product-catalog.xml") if err != nil { panic(err) } defer f.Close() var body bytes.Buffer writer := multipart.NewWriter(&body) part, err := writer.CreateFormFile("file", "product-catalog.xml") if err != nil { panic(err) } if _, err := io.Copy(part, f); err != nil { panic(err) } writer.Close() req, err := http.NewRequest("POST", "https://api.txtfetch.com/v1/extract", &body) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY")) req.Header.Set("Content-Type", writer.FormDataContentType()) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() var result extractResponse if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { panic(err) } fmt.Println(result.ExtractedText) } ``` Or skip the download. Pass a `url` parameter and txtfetch fetches the document server-side: curl ```curl curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/feeds/press-release.xml" \ -H "Authorization: Bearer $TXTFETCH_KEY" ``` Python ```python import os import requests r = requests.post( "https://api.txtfetch.com/v1/extract", headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"}, params={"url": "https://example.com/feeds/press-release.xml"}, ) print(r.json()["extracted_text"]) ``` JavaScript ```javascript const endpoint = new URL("https://api.txtfetch.com/v1/extract"); endpoint.searchParams.set("url", "https://example.com/feeds/press-release.xml"); const res = await fetch(endpoint, { method: "POST", headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` }, }); const { extracted_text } = await res.json(); console.log(extracted_text); ``` Go ```go package main import ( "encoding/json" "fmt" "net/http" "net/url" "os" ) type extractResponse struct { Status string `json:"status"` ExtractedText string `json:"extracted_text"` } func main() { endpoint, err := url.Parse("https://api.txtfetch.com/v1/extract") if err != nil { panic(err) } q := endpoint.Query() q.Set("url", "https://example.com/feeds/press-release.xml") endpoint.RawQuery = q.Encode() req, err := http.NewRequest("POST", endpoint.String(), nil) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() var result extractResponse if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { panic(err) } fmt.Println(result.ExtractedText) } ``` ``` { "status": "success", "extracted_text": "..." } ``` what-comes-back The corpus behind [/diff](https://txtfetch.com/diff) has no recorded .xml document yet, so we have nothing honest to show you here. Run one of your own instead. The [free converter](https://txtfetch.com/tools/file-to-text) reads the file in your browser, and nothing is uploaded. formats-covered - `.xml` - `.json` - `.yaml` - `.html` - `.xhtml` - `.svg` response-options Need the element structure, not flattened prose? ?format=json returns a typed element tree instead of one text blob. faq **Does extraction resolve HTML/XML entities like & or ’?**: Yes. Entities resolve to the character they represent in the extracted text rather than being left as literal escape sequences. **Is content inside CDATA sections included?**: Yes. CDATA blocks are parsed as the raw content they contain, not skipped or double-escaped. **What about content stored in XML attributes rather than element text, like in DITA or XBRL files?**: Common technical and financial XML dialects (DITA, DocBook, JATS, XBRL) carry meaningful content in specific attributes, not just element text. txtfetch's XML handling accounts for this rather than only reading text nodes. **Can I get a structured element tree instead of flattened text?**: Yes. Pass ?format=json for a typed, hierarchical view of the document instead of prose-flattened text. go-further - [API quickstart →](https://txtfetch.com/docs) - [How the pipeline works →](https://txtfetch.com/how-it-works) - [Extract it from your language →](https://txtfetch.com/for) - [Get an API key →](https://app.txtfetch.com/signup) Web & data - [`.html`](https://txtfetch.com/extract/html) - [`.csv`](https://txtfetch.com/extract/csv) - [All formats →](https://txtfetch.com/extract) ## Send a real .xml through it. One HTTP call returns the text. Read one in your browser first, for free. [Get an API key →](https://app.txtfetch.com/signup) [Open the free .xml reader →](https://txtfetch.com/tools/file-to-text)