תקציר המאמר:
מאמר זה סוקר את השינויים העיקריים שחלו בגרסה החדשה של 2.0 System.Xml. בין השינויים שנסקור:
|
|
תהליך המרת ערכים של ערכי ה-XML לסוגים שונים של ערכי ה-NET.
|
|
|
קריאה של ערכים גדולים
|
|
|
חיפוש אלמנטים (nodes)
|
|
|
כתיבה ל-XML
|
|
|
ולידציה (Validation)
|
|
|
טעינה ושמירה
|
|
|
ניווטים ושאילתות
|
|
|
|
|
מטרות היעד של System.Xml 2.0
|
|
שיפור הביצועים של System.Xml היה המניע העיקרי מאחורי השינויים הרבים שבוצעו ב-2.0 System.Xml. בהשוואה לגרסה המקורית .NET Framework 1.1, ה-class-ים החדשים של XmlTextReader ו- XmlTextWriter מהירים פי 2 לעומת הגרסה הקודמת, הביצועים של XSLT מהירים פי 3 או 4 והוולידציה של XML Schema מהירה ב-20% עד 25%. אבל כדי להשיג את המרב משיפור הביצועים נדרש תכנון ומיטוב המטרות מחדש.
|
|
|
|
קריאת ה-(Xml Reader) XML
|
|
כשאנו צריכים לקרוא XML במהירות וביעילות מקסימלית עלינו להשתמש ב-XmlReader, המספק מודל שליפה של קריאת אלמנט (node) בודד בכל פעם במהלך המעבר על הקובץ מהתחלה ועד הסוף למטרת קריאה בלבד. XmlReader הוא class בסיס אבסטרקטי וקיים מספר מצומצם של class-ים היורשים ממנו כמו XmlTextReader, XmlValidatingReader, ו-class-ים פנימיים אחרים המשמשים את הספרייה.
|
|
|
|
אחד השינויים העיקריים בגרסה 2.0 הוא שיטת היצירה של אובייקטים מסוג XmlReader. בגרסאות הקודמות היה צורך לבחור את ה-XmlReader class ולהגדיר אותו ישירות. זה דרש היכרות עם כל הclass-ים היורשים מ- XmlReader, והיכרות עם כל המאפיינים הייחודיים שלהם. הדרך המומלצת ליצירת אובייקט מסוג XmlReader בגרסה 2.0 היא שימוש בפקודה סטטית של Create, החוסכת מאיתנו את המימוש הבסיסי של האובייקט. הדוגמה הבאה מראה איך ליצור מופע של אובייקט מסוג XmlReader מקובץ "Order.xml”:
|
|
|
|
|
בדוגמה זו נוצר מופע של XmlReader על ידי שימוש בהגדרות בסיסיות. את ה-XmlReader ניתן לערוך על ידי הוספת XmlReaderSettings לפעולת היצירה של האובייקט. בדוגמה הבאה פקודת הקריאה מתעלמת מרווחים, הערות ומ-(Document Type Definition) DTD:
|
|
|
|
|
היתרון הבולט בשימוש בתבניות אלה הוא בכך שהוא חוסך את המימוש הבסיסי ואת פרטי הקונפיגורציה. כעת נוכל להתרכז ב-class XmlReaderSettings וניתן לפקודת ה-Create לבצע את כל העבודה.
|
|
|
|
סגירה נכונה של אובייקט XmlReader היא מאוד חשובה. בגרסה 1.1 היינו חייבים לקרוא בזמן הנכון לפקודת ה- Close. לעומת זאת בגרסה System.Xml 2.0, ה-class הבסיסי שלXmlReader מיישם את IDisposable ומאפשר את השימוש הבא:
|
|
|
|
|
בסוף פקודת ה- using ממומש ה- Dispose, הקורא לפקודת ה-Close של האובייקט.
|
|
|
|
המרת ערכים (Converting Values)
|
|
בנוסף לכל מה שכבר נאמר עד כה גרסה 2.0 גם מקלה עלינו בתהליך ההמרה של ערכי ה-XML לסוגים שונים של ערכי ה- NET. בעזרת הדוגמה הבאה ניתן לראות חלק מהאפשרויות.
|
|
|
|
נניח שהמשימה שלנו היא לקרוא את תוכן כל המחירים ("<Price>") כערכי System.Double. בגרסה הקודמת היינו מבצעים זאת על ידי קריאת הערך, הפיכתו למחרוזת (string) ואחר כך משתמשים
ב-class ה- XmlConvert כדי להמיר את המחרוזת באופן ידני לערך System.Double. בגלל הפעמים הרבות שבהם יש צורך בביצוע פעולות אלה, זה הופך למעיק מאוד. לכן בגרסה System.Xml 2.0 הותאמו מספר מתודות שיבצעו עבורנו את הפעולות הללו.
קיימות שתי מתודות שאפשר לבחור מהן:
|
|
|
ReadContentAsXXX – ניתן להשתמש ב- ReadContentAsXXX כאשר הסמן כבר ממוקם על הטקסט או על התכונה של האלמנט.
|
|
|
ReadElementContentAsXXX – ניתן להשתמש ב- ReadElementContentAsXXX כשהסמן ממוקם בתחילת האלמנט ואנחנו רוצים לעבור על התוכן ולקדם את הסמן לסוף האלמנט.
|
|
|
|
|
דוגמה לשימוש ב- ReadElementContentAsDouble:
|
|
|
|
|
ישנה מתודה נפרדת עבור כל סוג בסיסי של .NET (כמו ReadElementContentAsBoolean ReadElementContentAsDateTime ,ReadElementContentAsDecimal וכדומה) ותמיד אפשר להשתמש ב-ReadElementContentAsString, כשאין מתודה מתאימה יותר. יש מתודות דומות גם עבור ReadContentAsXXX וקיימת אפשרות של שימוש גנרי (generic) במתודות ReadContentAs וב- ReadElementContentAs להגדרות דינמיות של סוגי הפרמטרים בNET.. אחת הסיבות לשימוש בהם היא כשאנחנו רוצים להפוך רשימה המופרדת ברווחים לבנים למערך. למשל "<Price>", המכיל את הרשימה הבאה:
|
|
|
|
|
ניתן להמיר את "<Price>" למערך מסוג double, כפי שמופיע בדוגמה הבאה:
|
|
|
|
|
קריאה של ערכים גדולים
|
|
ה- XmlReader החדש יכול לקרוא חלקים של הערך בכל פעם. ניתן להשתמש ב- ReadContentAsBase64 או ב- ReadContentAsBinHex כשצריך להמיר חלקי טקסט אשר מקודדים ב- Base64 או ב- BinHex .System.Xml מספק גם ReadElementContentAsBase64
ו- ReadElementContentAsBinHex כשיש צורך לקרוא מהאובייקט ערכים כאלה.
|
|
|
|
חיפוש אלמנטים (nodes)
|
|
יחד עם כל השיפורים System.Xml 2.0 מספקת מספר מתודות, שבעזרתן אפשר למצוא בקלות את האלמנט הרצוי בקובץ על ידי שימוש ב-ReadToDescendant ,ReadToFollowing וגם
ב-ReadToSibling. מתודות אלה עוברות על רצף האלמנטים בסדר מסוים.
|
|
|
אם רוצים למצוא את האלמנט של "<Price>" בעץ ספציפי, נשתמש ב- ReadToDescendant.
|
|
|
אם רוצים למצוא "<Price>" שמופיע איפה שהוא אחרי האלמנט הנוכחי, נשתמש ב- ReadToFollowing.
|
|
|
ולבסוף כשרוצים למצוא את האלמנט המתאים הבא נשתמש ב-ReadToNextSibling.
|
|
|
|
|
דוגמה לכל אחת מהמתודות:
|
|
|
|
|
כתיבה
|
כשצריך לכתוב ל-XML הדרך היעילה והמהירה היא להשתמש ב- XmlWriter. המבנה של XmlWriter מאוד דומה למבנה של XmlReader, כשהפעם נתמקד בכתיבה לצמתי ה-XML.
רוב השיפורים של XmlWriter דומים לשיפורים של XmlReader:
|
|
|
בשלב ראשון - עלינו ליצור אובייקט XmlWriter על ידי מתודת Create.
|
|
|
בשלב השני - נשתמש ב-XmlWriterSettings כדי להגדיר את הגדרות הפלט של האובייקט.
|
|
|
בשלב האחרון של XmlWriter נממש גם את ה- IDisposable, כפי שמופיע בדוגמא הבאה:
|
|
|
|
|
|
עבור הקלט הבא יתקבל הפלט הזה: "GREAL", 1037.50 ו- 3 כמספר פרמטרים למתודת הכתיבה.
בנוסף לשיפורים אלה, XmlWriter נותן גם תמיכה בהמרה של ערכים תוך כדי ביצוע הכתיבה.
|
|
|
|
|
|
|
אפשר לראות זאת בדוגמה הבאה:
|
|
|
|
|
|
|
ולידציה (Validation)
|
|
כאשר רוצים לבדוק את תקינות ה-XML, אפשר פשוט להגדיר את ה- XmlReaderSettings בהתאם. הדוגמה הבאה מראה כיצד ניתן להגדיר את הולידציה של XML Schema החדשה:
|
|
|
|
הקריאה ל-Create גורמת לאובייקטים של XmlReader להיווצר ולהשתרשר אחד אחרי השני, אחת עבור קריאת רצף של טקסטים (XmlTextReaderImpl), והשניה עבור ביצוע הולידציה (XsdValidatingReader). היופי בעניין הוא שלא צריך להתמודד עם הגדרת האובייקטים ישירות.
|
|
|
|
טעינה ושמירה
|
|
כשרוצים לטעון את מסמך ה-XML לתוך הזיכרון ניתן להשתמש בשיטות ניווט מתוחכמות, כשה- System.Xml מספק מספר אפשרויות. קודם כל קיים מימוש למודל ה-W3C Document Object Model (DOM) בעזרת XmlDocument class, שרוב המפתחים משתמשים בו בשנים האחרונות.
XmlDocument חושף את מתודת ה-Load עבור הקריאה של הקובץ מהרצף (על ידי שימוש ב- XmlReader) ו"טעינתו" לתוך הזיכרון של עץ האלמנטים. כמו כן הוא גם מספק את מתודת ה-Save (על ידי שימוש ב- XmlWriter). להלן דוגמה:
|
|
|
|
ברגע שהמסמך נטען לזיכרון ניתן להשתמש ב- DOM API או XPathNavigator עבור מעבר או עדכון הקובץ. למרות ש-DOM קיים בשימוש נרחב היום, הוא די כבד בשל מספר סוגיות. רוב הבעיות של
ה- DOM נובעות בגלל העובדה ש-API מנסה לשקף את הסינטקס של XML 1.0. כמו כן ה- DOM חושף ישירות אל המפתח את האלמנט עצמו, מה שרק מקשה על המפתח בתהליך היישום ובניהול יעיל של שטח האכסון.
לכן, System.Xml יצאה עם גישה אלטרנטיבית של שמירה בתוך הזיכרון הפנימי (in-memory store) המוכרת כ- XpathDocument. ה- XpathDocument מיועד לאכסון עבור קריאה בלבד של שאילתות וטרנספורמציות. הניווט של ה- XpathDocument מבוצע על ידי השימוש ב- XPathNavigator .
ניתן להשתמש ב- XPathNavigator כדי לכתוב בחזרה לקובץ באמצעות XmlWriter. כדי לעשות זאת אפשר לקרוא ל-XmlWriter.WriteNode ולספק את ה- XPathNavigator שאותו רוצים לרשום או לקרוא ל-XPathNavigator.WriteSubtree ולספק את ה- XmlWriter שאליו רוצים לכתוב, כמפורט בדוגמה הבאה. היתרון הבולט בשימוש ב- XPathDocument על XmlDocument הוא בכך שהניווט מהיר יותר, במיוחד כשמבצעים שאילתות וטרנזקציות. לרוב נשתמש ב- XmlDocument כדי לעדכן את הקובץ בזיכרון.
|
|
|
|
|
ניווטים ושאילתות
|
|
כאשר משתמשים ב- XPathDocument או ב- XmlDocument כזיכרון פנימי, מומלץ להשתמש
ב- XPathNavigator, המספק שכבת הגנה נוספת בין הקוד למופע של האובייקט וגם מכין אותנו לשיפורים עתידיים. XPathNavigator מספק מתודות מספריות MoveToXXX לניווט בזיכרון לפי מסלולים שונים (צאצאים, אחים, עוקבים וכדומה). כמו ה-XmlReader, גם ה- XPathNavigator משתמש בגישת הסמן למטרות הניווט בקובץ. ברגע שנמצאים על האלמנט, ניתן לגשת לכל המאפיינים שלו. בגרסה 2.0 מספר סוגים ניתנים להמרה פשוטה על ידי ValueAsXXX, כפי שמופיעים בדוגמה הבאה:
|
|
|
|
|
כמו כן, השימוש בביטויים של Xpath בקרב מפתחים הוא די נפוץ, כדי לנווט דרך המסמך. XPathNavigator מספק תמיכה גם במספר מגוון של פקודות Select של ה-Xpath (כמו SelectAncestors, SelectChildren, SelectDescendants וכדומה). ניתן גם להשתמש
ב- SelectSingleNode, כדי למצוא את האלמנט המתאים הראשון.
|
|
|
|
לסיכום
|
|
הגרסה System.Xml 2.0 משופרת, יעילה יותר, ומספקת פתרונות נקיים עבור פעולות שימושיות של ה- XML שמומלץ להשתמש בהם:
|
|
|
השתמשו תמיד במתודה סטטית של Create עבור קריאה וכתיבה וגם רק בשביל הולידציה.
|
|
|
אם היעילות חשובה לכם, השתמשו ב- XPathDocument כזיכרון פנימי, בזמן ביצוע השאילתות והטרנספורמציה על הקובץ.
|
|
|
השתמשו ב- XmlDocument רק כשאתם באמת צריכים לערוך את הקובץ. בכל מקרה של כתיבת לוגיקה השתמשו ב- XPathNavigator.
|
|
|
|