XML to JSON 변환기
XML을 JSON 형식으로 변환
XML 입력
JSON 출력
XML to JSON 변환이란?
XML to JSON 변환은 확장 가능한 마크업 언어(XML)의 데이터를 JavaScript Object Notation(JSON)으로 변환하는 과정입니다. 두 형식 모두 구조화된 계층적 데이터를 표현하지만, 서로 다른 문법과 데이터 모델을 사용합니다. XML은 선택적 속성이 있는 여는 태그와 닫는 태그를 사용하고, JSON은 키-값 쌍, 배열, 기본 타입을 사용합니다. XML을 JSON으로 변환하면 JavaScript 런타임, REST API, NoSQL 데이터베이스처럼 JSON이 기본 형식인 환경에서 XML 데이터를 사용할 수 있습니다.
변환이 항상 일대일로 이루어지는 것은 아닙니다. XML에는 JSON에 직접적으로 대응하는 것이 없는 구성 요소가 있습니다: 속성, 혼합 콘텐츠(텍스트와 자식 요소가 혼재), 처리 지시문, 주석, CDATA 섹션, 네임스페이스 선언이 그것입니다. 변환 라이브러리마다 이러한 구성 요소를 다르게 처리하기 때문에 여러 관례가 존재합니다. 가장 일반적인 방식은 속성 이름에 @를 접두사로 붙이고, 같은 요소에 속성이 있을 때 텍스트 콘텐츠를 #text 필드에 넣는 것입니다.
XML to JSON 변환은 SOAP에서 REST로 마이그레이션하거나, 레거시 엔터프라이즈 API를 사용하거나, XML을 필수로 하는 정부 및 금융 데이터 피드를 처리할 때 흔히 사용됩니다. 생산자와 소비자를 동시에 재작성하는 대신, 경계 레이어에서 XML 페이로드를 변환하고 JSON을 하위로 전달합니다. AWS API Gateway, Apache Camel, MuleSoft 모두 이 패턴을 기본으로 지원합니다.
<bookstore>
<book category="fiction">
<title lang="en">The Great Gatsby</title>
<author>F. Scott Fitzgerald</author>
<year>1925</year>
<price>10.99</price>
</book>
<book category="non-fiction">
<title lang="en">Sapiens</title>
<author>Yuval Noah Harari</author>
<year>2011</year>
<price>14.99</price>
</book>
</bookstore>{
"bookstore": {
"book": [
{
"@category": "fiction",
"title": {
"@lang": "en",
"#text": "The Great Gatsby"
},
"author": "F. Scott Fitzgerald",
"year": "1925",
"price": "10.99"
},
{
"@category": "non-fiction",
"title": {
"@lang": "en",
"#text": "Sapiens"
},
"author": "Yuval Noah Harari",
"year": "2011",
"price": "14.99"
}
]
}
}온라인 XML to JSON 변환기를 사용하는 이유
일회성 변환 스크립트를 작성하는 것은 시간이 걸립니다. 특히 XML에 JSON 배열이 되어야 할 속성, 네임스페이스, 반복 요소가 포함된 경우에는 더욱 그렇습니다. 브라우저 기반 변환기는 몇 초 만에 JSON 출력을 제공하므로 구조를 확인하고 바로 작업을 계속할 수 있습니다.
XML to JSON 활용 사례
XML to JSON 매핑 참조
XML과 JSON은 서로 다른 데이터 모델을 가집니다. 아래 표는 가장 일반적인 관례(속성에는 @, 속성과 함께 있는 텍스트에는 #text)에 따라 각 XML 구성 요소가 JSON으로 어떻게 매핑되는지 보여줍니다. 혼합 콘텐츠나 주석 같은 일부 구성 요소는 표준 JSON 표현이 없습니다.
| XML 구성 요소 | XML 예시 | JSON 동등값 |
|---|---|---|
| Element | <name>text</name> | "name": "text" |
| Nested elements | <a><b>1</b></a> | "a": { "b": "1" } |
| Attributes | <el attr="v"/> | "el": { "@attr": "v" } |
| Text + attributes | <el a="1">text</el> | "el": { "@a": "1", "#text": "text" } |
| Repeated elements | <r><i>1</i><i>2</i></r> | "r": { "i": ["1", "2"] } |
| Mixed content | <p>A <b>B</b> C</p> | Varies by convention |
| CDATA | <![CDATA[raw]]> | "#cdata": "raw" or flattened |
| Namespaces | xmlns:prefix="uri" | Prefix preserved or stripped |
| Empty element | <el/> | "el": null or "" |
| Comments | <!-- note --> | Discarded (no JSON equivalent) |
XML to JSON 관례 비교
XML이 JSON으로 매핑되는 방식을 규정하는 단일 표준은 없습니다. 세 가지 관례가 널리 사용되며, 각각 속성 처리, 배열 감지, 텍스트 보존에서 서로 다른 장단점이 있습니다.
코드 예제
아래는 JavaScript, Python, Go, 명령줄에서 XML을 JSON으로 변환하는 실제 예제입니다. 각 예제는 중첩 요소와 반복되는 형제 태그를 처리합니다.
// Using the DOMParser API to walk XML and build a JSON object
function xmlToJson(xml) {
const parser = new DOMParser()
const doc = parser.parseFromString(xml, 'application/xml')
function nodeToObj(node) {
const obj = {}
// Handle attributes
if (node.attributes) {
for (const attr of node.attributes) {
obj['@' + attr.name] = attr.value
}
}
// Handle child nodes
for (const child of node.childNodes) {
if (child.nodeType === 3) { // text
const text = child.textContent.trim()
if (text) obj['#text'] = text
} else if (child.nodeType === 1) { // element
const key = child.nodeName
const val = nodeToObj(child)
if (obj[key]) {
if (!Array.isArray(obj[key])) obj[key] = [obj[key]]
obj[key].push(val)
} else {
obj[key] = val
}
}
}
// Simplify text-only nodes
const keys = Object.keys(obj)
if (keys.length === 1 && keys[0] === '#text') return obj['#text']
return obj
}
return nodeToObj(doc.documentElement)
}
const xml = '<user><name>Alice</name><role>admin</role></user>'
console.log(JSON.stringify(xmlToJson(xml), null, 2))
// → { "name": "Alice", "role": "admin" }import xmltodict
import json
xml = """
<user>
<name>Alice</name>
<roles>
<role>admin</role>
<role>editor</role>
</roles>
</user>
"""
# xmltodict converts XML to an OrderedDict
result = xmltodict.parse(xml)
print(json.dumps(result, indent=2))
# → {
# → "user": {
# → "name": "Alice",
# → "roles": { "role": ["admin", "editor"] }
# → }
# → }
# With the standard library (xml.etree.ElementTree)
import xml.etree.ElementTree as ET
def etree_to_dict(elem):
d = {}
if elem.attrib:
d.update({f"@{k}": v for k, v in elem.attrib.items()})
for child in elem:
child_data = etree_to_dict(child)
if child.tag in d:
if not isinstance(d[child.tag], list):
d[child.tag] = [d[child.tag]]
d[child.tag].append(child_data)
else:
d[child.tag] = child_data
if elem.text and elem.text.strip():
if d:
d["#text"] = elem.text.strip()
else:
return elem.text.strip()
return d
root = ET.fromstring(xml)
print(json.dumps(etree_to_dict(root), indent=2))package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"strings"
)
// For simple, known schemas — define a struct
type User struct {
XMLName xml.Name `xml:"user"`
Name string `xml:"name"`
Roles []string `xml:"roles>role"`
}
func main() {
data := `<user><name>Alice</name><roles><role>admin</role><role>editor</role></roles></user>`
var user User
xml.NewDecoder(strings.NewReader(data)).Decode(&user)
out, _ := json.MarshalIndent(user, "", " ")
fmt.Println(string(out))
// → { "Name": "Alice", "Roles": ["admin", "editor"] }
}# Using xq (part of yq, a jq wrapper for XML)
# Install: pip install yq OR brew install yq
echo '<user><name>Alice</name></user>' | xq .
# → { "user": { "name": "Alice" } }
# Using xmlstarlet + jq
xmlstarlet sel -t -v '//name' input.xml | jq -R '{ name: . }'
# Node.js one-liner with xml2js
echo '<a><b>1</b></a>' | node -e "
const {parseString} = require('xml2js');
let d=''; process.stdin.on('data',c=>d+=c);
process.stdin.on('end',()=>parseString(d,(e,r)=>console.log(JSON.stringify(r,null,2))))
"