فشردهساز XML
فشردهسازی XML با حذف فاصلههای اضافی و کامنتها
ورودی XML
XML فشردهشده
فشردهسازی XML چیست؟
فشردهسازی XML فرآیند حذف تمام کاراکترهای غیرضروری از یک سند XML بدون تغییر معنای آن است. یک فشردهساز XML فاصلههای بین تگها را حذف میکند، کامنتها را پاک میکند، شکست خطوط را از بین میبرد و تورفتگی را حذف میکند تا خروجی فشردهای در یک خط تولید کند. نتیجه یک رشته XML است که پارسرها آن را کاملاً یکسان با نسخه فرمتشده اصلی میخوانند و همان مدل داده را تولید میکنند.
مشخصه XML 1.0 (توصیه W3C، ویرایش پنجم) قوانین مدیریت فاصله را در بخش ۲.۱۰ تعریف میکند. فاصلههای بین تگهایی که ارزش معنایی ندارند «فاصله غیرمعنایی» نامیده میشوند. پردازندههای XML میتوانند آنها را حذف کنند. اما فاصلههای داخل محتوای متنی به صورت پیشفرض معنادار هستند، مگر اینکه عنصر والد xml:space="default" اعلان کند. یک فشردهساز صحیح XML بین این دو حالت تمایز قائل میشود و تنها آنچه را که حذف آن بیخطر است پاک میکند.
مینیفای کردن با فشردهسازی داده (compression) تفاوت دارد. Gzip یا Brotli حجم را در لایه انتقال کاهش میدهند و قبل از تجزیه نیاز به رمزگشایی دارند. فشردهسازی XML حجم خود سند خام را کاهش میدهد، بنابراین XML همچنان معتبر است و بدون نیاز به رمزگشایی توسط هر پارسری قابل خواندن است. در عمل، فشردهسازی قبل از فشردهسازی بهترین نتیجه را میدهد: ابتدا کاراکترهای اضافی را حذف میکنید، سپس الگوریتم فشردهسازی روی ورودی کوچکتری کار میکند.
<?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 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 استفاده کنیم؟
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 |
فشردهسازی XML در مقابل Gzip در مقابل فرمتهای باینری
فشردهسازی، فشردهسازی داده و رمزگذاری باینری هر کدام لایه متفاوتی از مشکل حجم را هدف قرار میدهند. فشردهسازی XML خروجی را به صورت 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"