منسّق XML
تنسيق XML وطباعته بصورة جميلة مع تمييز صياغي
إدخال XML
XML منسّق
ما هو تنسيق XML؟
تنسيق XML (المعروف أيضًا بالطباعة الجميلة لـXML أو تجميل XML) هو عملية إضافة مسافات بادئة وفواصل أسطر متسقة إلى مستند XML بحيث تتضح بنيته الهرمية. كثيرًا ما يُسلَّم XML الخام الوارد من واجهات برمجة التطبيقات أو مولّدات الضبط أو أدوات التسلسل في سطر واحد دون أي مسافات بيضاء بين الوسوم. يُحلّل منسّق XML المستند إلى شجرة، ثم يُعيد تسلسله بتباعد منتظم وقابل للتنبؤ.
تحدد مواصفة XML 1.0 (توصية W3C، الطبعة الخامسة) قواعد نحوية صارمة: يجب أن يكون لكل وسم افتتاحي وسم إغلاق مطابق أو أن يكون وسمًا ذاتي الإغلاق، ويجب أن تكون قيم الخصائص بين علامات اقتباس، وتستلزم خمسة أحرف (<، >، &، "، ') الاستعاضة عنها بكيانات محددة مسبقًا. يجب أن يحترم المنسّق هذه القواعد مع إدراج مسافات بيضاء غير ذات دلالة لا تؤثر في مجموعة المعلومات (infoset) للمستند.
يسهل قراءة XML المنسّق أثناء مراجعة الكود، ويُبسّط مقارنة الفروق في نظام التحكم في الإصدارات، ويُيسّر تصحيح الأخطاء حين تُعيد خدمة ما بيانات غير متوقعة. عملية التنسيق نفسها لا تنطوي على أي فقدان للمحتوى: يبقى المحتوى المنطقي للمستند مطابقًا، ولا يتغير سوى العرض التقديمي. تُظهر أدوات مثل git diff ومنصات مراجعة طلبات السحب الأسطر المعدّلة فقط — وXML المنسّق باتساق يضمن أن تعكس الفروق تغييرات حقيقية لا ضوضاء إعادة التنسيق.
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
</book>
</catalog><catalog><book id="bk101"><author>Gambardella, Matthew</author><title>XML Developer's Guide</title><genre>Computer</genre><price>44.95</price><publish_date>2000-10-01</publish_date></book><book id="bk102"><author>Ralls, Kim</author><title>Midnight Rain</title><genre>Fantasy</genre><price>5.95</price><publish_date>2000-12-16</publish_date></book></catalog>
لماذا تستخدم منسّق XML الإلكتروني؟
تنسيق XML يدويًا عملية عُرضة للأخطاء وبطيئة، لا سيما مع المستندات ذات التداخل العميق أو مساحات الأسماء المتعددة. يمنحك المنسّق المستند إلى المتصفح نتيجة منسّقة في أقل من ثانية بصرف النظر عن حجم الملف.
حالات استخدام منسّق XML
مرجع الكيانات المحددة مسبقًا في XML
يحجز XML خمسة أحرف لصياغته. عندما تظهر هذه الأحرف كمحتوى نصي حرفي أو قيم خصائص، يجب استبدالها بكيانات محددة مسبقًا. يحافظ المنسّق الصحيح على هذه الكيانات أثناء الطباعة الجميلة.
| الحرف | الدور في XML | الكيان |
|---|---|---|
| < | Start of tag | < |
| > | End of tag | > |
| & | Start of entity | & |
| " | Attribute delimiter | " |
| ' | Attribute delimiter | ' |
مقارنة أنماط مسافات XML البادئة
لا يوجد معيار موحّد واحد لمسافات XML البادئة. يعتمد الاختيار على اتفاقيات فريقك والأدوات في خط أنابيبك. إليك الأنماط الثلاثة الأكثر شيوعًا.
أمثلة على الكود: تنسيق XML برمجيًا
حين تحتاج إلى تنسيق XML داخل سكربت أو عملية بناء، توفر كل اللغات الرئيسية خيارًا مدمجًا أو في مكتبتها القياسية. فيما يلي أمثلة جاهزة للاستخدام يمكنك نسخها مباشرة.
const raw = '<root><item>hello</item></root>'
const parser = new DOMParser()
const doc = parser.parseFromString(raw, 'application/xml')
const serializer = new XMLSerializer()
const xml = serializer.serializeToString(doc)
// Indent with XSLT (browser-native approach)
const xslt = new DOMParser().parseFromString(`
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>`, 'application/xml')
const proc = new XSLTProcessor()
proc.importStylesheet(xslt)
const formatted = proc.transformToDocument(doc)
console.log(new XMLSerializer().serializeToString(formatted))
// → <root>\n <item>hello</item>\n</root>import xml.dom.minidom raw = '<root><item>hello</item><item>world</item></root>' dom = xml.dom.minidom.parseString(raw) print(dom.toprettyxml(indent=' ')) # → <?xml version="1.0" ?> # → <root> # → <item>hello</item> # → <item>world</item> # → </root> # With lxml (handles namespaces, XSD, large files) from lxml import etree tree = etree.fromstring(raw.encode()) print(etree.tostring(tree, pretty_print=True).decode())
package main
import (
"encoding/xml"
"fmt"
"strings"
)
func formatXML(raw string) (string, error) {
decoder := xml.NewDecoder(strings.NewReader(raw))
var out strings.Builder
encoder := xml.NewEncoder(&out)
encoder.Indent("", " ")
for {
tok, err := decoder.Token()
if err != nil {
break
}
encoder.EncodeToken(tok)
}
encoder.Flush()
return out.String(), nil
}
// formatXML("<a><b>1</b></a>") → "<a>\n <b>1</b>\n</a>"# Format XML file with xmllint (part of libxml2, pre-installed on macOS/Linux) xmllint --format input.xml > formatted.xml # Format from stdin echo '<a><b>1</b></a>' | xmllint --format - # → <?xml version="1.0"?> # → <a> # → <b>1</b> # → </a> # Validate and format at the same time xmllint --format --schema schema.xsd input.xml