XML Minifier
Мініфікує XML, видаляючи пробіли та коментарі
Введення XML
Мініфіковане XML
Що таке мінімізація XML?
Мінімізація XML — це процес видалення всіх зайвих символів з XML-документа без зміни його змісту. XML-мінімізатор прибирає пробіли між тегами, видаляє коментарі, усуває переноси рядків та згортає відступи, щоб отримати компактний однорядковий результат. Підсумковий рядок XML парсери читають ідентично до оригінальної відформатованої версії, відтворюючи ту саму модель даних.
Специфікація XML 1.0 (Рекомендація W3C, п'яте видання) визначає правила обробки пробілів у розділі 2.10. Пробіли між тегами, що не несуть семантичного значення, називають «незначущими пробілами». XML-процесорам дозволено їх відкидати. Однак пробіли всередині текстового вмісту є значущими за замовчуванням, якщо тільки батьківський елемент не оголошує xml:space="default". Коректний XML-мінімізатор розрізняє ці два випадки і видаляє лише те, що безпечно видаляти.
Мінімізація відрізняється від стиснення. Gzip або Brotli зменшують розмір на транспортному рівні й вимагають розпакування перед парсингом. Мінімізація зменшує розмір самого документа, тому XML залишається коректним і придатним для читання будь-яким парсером без кроку розпакування. На практиці мінімізація перед стисненням дає найкращий результат: спочатку усуваємо надлишкові символи, а потім алгоритм стиснення працює з компактнішим вхідним файлом.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Product catalog for Q1 2026 -->
<catalog>
<product id="p101">
<name>Widget A</name>
<price currency="USD">29.99</price>
<!-- Temporarily discounted -->
<stock>142</stock>
</product>
<product id="p102">
<name>Widget B</name>
<price currency="EUR">19.50</price>
<stock>87</stock>
</product>
</catalog><?xml version="1.0" encoding="UTF-8"?><catalog><product id="p101"><name>Widget A</name><price currency="USD">29.99</price><stock>142</stock></product><product id="p102"><name>Widget B</name><price currency="EUR">19.50</price><stock>87</stock></product></catalog>
Навіщо використовувати XML-мінімізатор?
XML з відступами та коментарями ідеально підходить для розробки та перегляду коду. Для зберігання, передачі та машинного опрацювання таке форматування додає байти без жодної користі. XML-мінімізатор усуває цю різницю.
Сценарії використання XML-мінімізатора
Що видаляє XML-мінімізатор
Не все в XML-документі можна безпечно видалити. Ця довідкова таблиця показує кожен тип вмісту, що підлягає видаленню, та чи є це завжди безпечним, чи залежить від конкретного сценарію використання.
| Елемент | Приклад | Безпека |
|---|---|---|
| Indentation | Spaces/tabs before tags | Always safe to remove |
| Line breaks | \n and \r\n between tags | Always safe to remove |
| Comments | <!-- ... --> | Safe unless parsed by app |
| XML declaration | <?xml version="1.0"?> | Keep if encoding is non-UTF-8 |
| Processing instructions | <?xml-stylesheet ...?> | Keep if consumed downstream |
| Trailing whitespace | Spaces after closing tags | Always safe to remove |
| Text node whitespace | Spaces inside text content | Remove only between tags, not within |
Мінімізація проти Gzip проти бінарних форматів
Мінімізація, стиснення та бінарне кодування вирішують проблему розміру на різних рівнях. Мінімізація зберігає результат як коректний, читабельний людиною XML. Стиснення (gzip, Brotli) зменшує розмір ще більше, але вимагає кроку розпакування перед парсингом. Бінарні формати йдуть найдалі, але обидва кінці з'єднання потребують сумісного кодувальника/декодувальника — що практично лише для вбудованих систем або корпоративних сервісів із великою кількістю WSDL.
Приклади коду
Програмна мінімізація XML слідує однаковому шаблону в кожній мові: розібрати документ у дерево, за потреби видалити вузли-коментарі, а потім серіалізувати без відступів.
// Minify XML by parsing and re-serializing (strips formatting)
const raw = `<root>
<item id="1">
<!-- note -->
<name>Test</name>
</item>
</root>`
const parser = new DOMParser()
const doc = parser.parseFromString(raw, 'application/xml')
// Remove comment nodes
const walker = doc.createTreeWalker(doc, NodeFilter.SHOW_COMMENT)
const comments = []
while (walker.nextNode()) comments.push(walker.currentNode)
comments.forEach(c => c.parentNode.removeChild(c))
const minified = new XMLSerializer().serializeToString(doc)
// → "<root><item id=\"1\"><name>Test</name></item></root>"from lxml import etree
xml = """<root>
<item id="1">
<!-- note -->
<name>Test</name>
</item>
</root>"""
tree = etree.fromstring(xml.encode())
# Remove comments
for comment in tree.iter(etree.Comment):
comment.getparent().remove(comment)
# Serialize without pretty-print (minified)
result = etree.tostring(tree, xml_declaration=False).decode()
# → '<root><item id="1"><name>Test</name></item></root>'
# With xml.etree (stdlib, no lxml needed)
import xml.etree.ElementTree as ET
root = ET.fromstring(xml)
ET.indent(root, space='') # Python 3.9+
print(ET.tostring(root, encoding='unicode'))package main
import (
"encoding/xml"
"fmt"
"strings"
)
func minifyXML(input string) (string, error) {
decoder := xml.NewDecoder(strings.NewReader(input))
var out strings.Builder
encoder := xml.NewEncoder(&out)
// No indentation = minified output
for {
tok, err := decoder.Token()
if err != nil {
break
}
// Skip comments
if _, ok := tok.(xml.Comment); ok {
continue
}
// Skip whitespace-only char data
if cd, ok := tok.(xml.CharData); ok {
if strings.TrimSpace(string(cd)) == "" {
continue
}
}
encoder.EncodeToken(tok)
}
encoder.Flush()
return out.String(), nil
}
// minifyXML("<a>\n <b>1</b>\n</a>") → "<a><b>1</b></a>"# Minify XML with xmllint (part of libxml2) xmllint --noblanks input.xml > minified.xml # Minify from stdin echo '<root> <item>hello</item> </root>' | xmllint --noblanks - # → <?xml version="1.0"?><root><item>hello</item></root> # Strip comments too (combine with sed or xmlstarlet) xmlstarlet ed -d '//comment()' input.xml | xmllint --noblanks - # Check size reduction echo "Before: $(wc -c < input.xml) bytes" echo "After: $(xmllint --noblanks input.xml | wc -c) bytes"