טעינה של Xhtml דרך XmlDocument

נוסף ב-07/09/2007 09:03 על ידי דניאל כץ

במאמר זה נביא מספר טיפים לשימוש במחלקות ממרחב שמות System.Xml מול תוכן Xhtml. וכן פתרונות לבעיות תאימות בין התקנים. הבעיות שנסקור כאן הם: איך לגרום לקורא Xml לא להתעלם מרווחים בין התגים, ואיך לקצר את זמן הטעינה על ידי דילוג על Validation מול www.w3.org.

דבר ראשון, נשים לב לבעיה קטנה שתצוץ בכל פעם שננסה לפתוח תוכן Xhtml ע"י מחלקות ממשפחת System.Xml, כל הרווחים שבין התגים ייעלמו לדוגמה השורה הבאה:

<span>Hello</span> <span>World</span>

למרות שבדפדפן היא תוצג כ"Hello World" כולל הרווח שבין התגים, Xml ינתח את התוכן כ"HelloWorld" ללא הרווח. את הבעיה הזאת אנו נתקן ע"י הגדרה של  PreserveWhitespace = True. הנה דוגמה:

Dim doc As New XmlDocument

doc.PreserveWhitespace = True

doc.Load("page.htm") ' דף בפורמט Xhtml

אך עדיין אתם תשימו לב לכך שהדף יטען רק כעבור כחצי שנייה שבה הפעילות של המעבד תעמוד על 0% בקירוב, אז מה  XmlDocument עושה בזמן היקר הזה?

מתברר שהוא מוריד  קובץ DTD מהמיקום: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd. ואח"כ מריץ אימות (Validation) מול הקובץ (האימות עצמו אורך זמן לא משמעותי כלל). כמובן אפשר לבטל את הוולידציה ע"י XmlReaderSettings, אבל - ראשית, זה לא ימנע את הורדת הקובץ שתופסת את רוב הזמן. ושנית, כאמור, הזמן של הוולידציה עצמה אינו משמעותי.

הפתרון יבוא בשני חלקים: קודם אנו נשמיט מתוכן הXhtml את התג שמציין את מקור הDTD. זה אמנם יביא לשיפור מיידי בביצועים אבל במקרה שהקובץ מכיל קודים מיוחדים כמו ;nbsp& שנתמכים בXhtml אבל אינם נתמכים בXml הסטנדרטי תיזרק שגיאה מסוג XmlException. כדי למנוע זאת אנו נחליף את כל הקודים המיוחדים לקודים סטנדרטיים המציינים את מספר הUnicode של התו.

הנה הפתרון המלא:

Public Shared html_entities As String() = New String() {"&quot;", "&apos;", "&amp;", "&lt;", "&gt;", "&nbsp;", "&iexcl;", "&curren;", "&cent;", "&pound;", "&yen;", "&brvbar;", "&sect;", "&uml;", "&copy;", "&ordf;", "&laquo;", "&not;", "&shy;", "&reg;", "&trade;", "&macr;", "&deg;", "&plusmn;", "&sup2;", "&sup3;", "&acute;", "&micro;", "&para;", "&middot;", "&cedil;", "&sup1;", "&ordm;", "&raquo;", "&frac14;", "&frac12;", "&frac34;", "&iquest;", "&times;", "&divide;", "&Agrave;", "&Aacute;", "&Acirc;", "&Atilde;", "&Auml;", "&Aring;", "&AElig;", "&Ccedil;", "&Egrave;", "&Eacute;", "&Ecirc;", "&Euml;", "&Igrave;", "&Iacute;", "&Icirc;", "&Iuml;", "&ETH;", "&Ntilde;", "&Ograve;", "&Oacute;", "&Ocirc;", "&Otilde;", "&Ouml;", "&Oslash;", "&Ugrave;", "&Uacute;", "&Ucirc;", "&Uuml;", "&Yacute;", "&THORN;", "&szlig;", "&agrave;", "&aacute;", "&acirc;", "&atilde;", "&auml;", "&aring;", "&aelig;", "&ccedil;", "&egrave;", "&eacute;", "&ecirc;", "&euml;", "&igrave;", "&iacute;", "&icirc;", "&iuml;", "&eth;", "&ntilde;", "&ograve;", "&oacute;", "&ocirc;", "&otilde;", "&ouml;", "&oslash;", "&ugrave;", "&uacute;", "&ucirc;", "&uuml;", "&yacute;", "&thorn;", "&yuml;", "&OElig;", "&oelig;", "&Scaron;", "&scaron;", "&Yuml;", "&circ;", "&tilde;", "&ensp;", "&emsp;", "&thinsp;", "&zwnj;", "&zwj;", "&lrm;", "&rlm;", "&ndash;", "&mdash;", "&lsquo;", "&rsquo;", "&sbquo;", "&ldquo;", "&rdquo;", "&bdquo;", "&dagger;", "&Dagger;", "&hellip;", "&permil;", "&lsaquo;", "&rsaquo;", "&euro;"}

Public Shared xml_entities As String() = New String() {"&#34;", "&#39;", "&#38;", "&#60;", "&#62;", "&#160;", "&#161;", "&#164;", "&#162;", "&#163;", "&#165;", "&#166;", "&#167;", "&#168;", "&#169;", "&#170;", "&#171;", "&#172;", "&#173;", "&#174;", "&#8482;", "&#175;", "&#176;", "&#177;", "&#178;", "&#179;", "&#180;", "&#181;", "&#182;", "&#183;", "&#184;", "&#185;", "&#186;", "&#187;", "&#188;", "&#189;", "&#190;", "&#191;", "&#215;", "&#247;", "&#192;", "&#193;", "&#194;", "&#195;", "&#196;", "&#197;", "&#198;", "&#199;", "&#200;", "&#201;", "&#202;", "&#203;", "&#204;", "&#205;", "&#206;", "&#207;", "&#208;", "&#209;", "&#210;", "&#211;", "&#212;", "&#213;", "&#214;", "&#216;", "&#217;", "&#218;", "&#219;", "&#220;", "&#221;", "&#222;", "&#223;", "&#224;", "&#225;", "&#226;", "&#227;", "&#228;", "&#229;", "&#230;", "&#231;", "&#232;", "&#233;", "&#234;", "&#235;", "&#236;", "&#237;", "&#238;", "&#239;", "&#240;", "&#241;", "&#242;", "&#243;", "&#244;", "&#245;", "&#246;", "&#248;", "&#249;", "&#250;", "&#251;", "&#252;", "&#253;", "&#254;", "&#255;", "&#338;", "&#339;", "&#352;", "&#353;", "&#376;", "&#710;", "&#732;", "&#8194;", "&#8195;", "&#8201;", "&#8204;", "&#8205;", "&#8206;", "&#8207;", "&#8211;", "&#8212;", "&#8216;", "&#8217;", "&#8218;", "&#8220;", "&#8221;", "&#8222;", "&#8224;", "&#8225;", "&#8230;", "&#8240;", "&#8249;", "&#8250;", "&#8364;"}

 

Public Shared Function XhtmlToXml(ByVal xhtml As String) As String

    xhtml = Regex.Replace(xhtml, "<!DOCTYPE\s.*>", "", RegexOptions.IgnoreCase)

    xhtml = Regex.Replace(xhtml, "&\w+;", New MatchEvaluator(AddressOf ReplaceEntity))

 

    Return xhtml

End Function

 

Private Shared Function ReplaceEntity(ByVal m As Match) As String

    Dim index As Integer = Array.IndexOf(html_entities, m.Value)

 

    If index >= 0 Then

        Return xml_entities(index)

    Else

        Return m.Value

    End If

End Function

וזהו תסריט השימוש הרצוי:

Dim xml As String = XhtmlToXml(File.ReadAllText("page.htm")) ' דף בפורמט Xhtml

Dim doc As New XmlDocument

doc.PreserveWhitespace = True

doc.LoadXml(xml)

Tags: , ,

.NET

הוסף תגובה


(יציג את האייקון ה-Gravatar שלך)

  Country flag

biuquote
  • הערה
  • תצוגה מקדימה
Loading