browserutilities/feedsengine/FeedsServer/XmlUtils/src/XmlEntity.cpp
changeset 0 dd21522fd290
child 36 0ed94ceaa377
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Resolves entities.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <EscapeUtils.h>
       
    21 #include <libxml2_xmlmemory.h>
       
    22 #include <libxml2_globals.h>
       
    23 
       
    24 #include "CleanupLibXml2.h"
       
    25 #include "LeakTracker.h"
       
    26 #include "XmlEntity.h"
       
    27 
       
    28 
       
    29 // Private consts.
       
    30 // -------------------------------------------------------------------------
       
    31 // Note:		This array must be sorted by entity name.  The lookup function
       
    32 //				does a binary search. */
       
    33 
       
    34 // IMPORTANT:	When you update this table make sure the constant 
       
    35 //				NW_XHTML_Num_CaseInsensitive_Entries which is the count of 
       
    36 //				caseinsensitive entries is updated correctly.
       
    37 
       
    38 // Note:        See http://kellyjones.netfirms.com/webtools/ascii_utf8_table.html
       
    39 //              for utf8 entity mappings.
       
    40 
       
    41 
       
    42 #define KNumCaseInsensitiveEntries 126
       
    43 
       
    44 static const CXmlEntity::EntityEntry  sSpaceEntity = { " ",      32 };
       
    45 
       
    46 static const CXmlEntity::EntityEntry sEntityMappings[] = 
       
    47     {
       
    48 // CaseSensitive entries
       
    49     { "AElig",      198 },
       
    50     { "Aacute",     193 },
       
    51     { "Acirc",      194 },
       
    52     { "Agrave",     192 },
       
    53     { "Alpha",      913 },
       
    54     { "Aring",      197 },
       
    55     { "Atilde",     195 },
       
    56     { "Auml",       196 },
       
    57     { "Beta",       914 },
       
    58     { "Ccedil",     199 },
       
    59     { "Chi",        935 },
       
    60     { "Dagger",     8225 },
       
    61     { "Delta",      916 },
       
    62     { "ETH",        208 },
       
    63     { "Eacute",     201 },
       
    64     { "Ecirc",      202 },
       
    65     { "Egrave",     200 },
       
    66     { "Epsilon",    917 },
       
    67     { "Eta",        919 },
       
    68     { "Euml",       203 },
       
    69     { "Gamma",      915 },
       
    70     { "Iacute",     205 },
       
    71     { "Icirc",      206 },
       
    72     { "Igrave",     204 },
       
    73     { "Iota",       921 },
       
    74     { "Iuml",       207 },
       
    75     { "Kappa",      922 },
       
    76     { "Lambda",     923 },
       
    77     { "Mu",         924 },
       
    78     { "Ntilde",     209 },
       
    79     { "Nu",         925 },
       
    80     { "OElig",      338 },
       
    81     { "Oacute",     211 },
       
    82     { "Ocirc",      212 },
       
    83     { "Ograve",     210 },
       
    84     { "Omega",      937 },
       
    85     { "Omicron",    927 },
       
    86     { "Oslash",     216 },
       
    87     { "Otilde",     213 },
       
    88     { "Ouml",       214 },
       
    89     { "Phi",        934 },
       
    90     { "Pi",         928 },
       
    91     { "Prime",      8243 },
       
    92     { "Psi",        936 },
       
    93     { "Rho",        929 },
       
    94     { "Scaron",     352 },
       
    95     { "Sigma",      931 },
       
    96     { "THORN",      222 },
       
    97     { "Tau",        932 },
       
    98     { "Theta",      920 },
       
    99     { "Uacute",     218 },
       
   100     { "Ucirc",      219 },
       
   101     { "Ugrave",     217 },
       
   102     { "Upsilon",    933 },
       
   103     { "Uuml",       220 },
       
   104     { "Xi",         926 },
       
   105     { "Yacute",     221 },
       
   106     { "Yuml",       376 },
       
   107     { "Zeta",       918 },
       
   108     { "aacute",     225 },
       
   109     { "acirc",      226 },
       
   110     { "acute",      180 },
       
   111     { "aelig",      230 },
       
   112     { "agrave",     224 },
       
   113     { "alpha",      945 },
       
   114     { "atilde",     227 },
       
   115     { "auml",       228 },
       
   116     { "beta",       946 },
       
   117     { "ccedil",     231 },
       
   118     { "chi",        967 },
       
   119     { "dArr",       8659 },
       
   120     { "dagger",     8224 },
       
   121     { "darr",       8595 },
       
   122     { "delta",      948 },
       
   123     { "eacute",     233 },
       
   124     { "ecirc",      234 },
       
   125     { "egrave",     232 },
       
   126     { "epsilon",    949 },
       
   127     { "eta",        951 },
       
   128     { "euml",       235 },
       
   129     { "gamma",      947 },
       
   130     { "hArr",       8660 },
       
   131     { "harr",       8596 },
       
   132     { "iacute",     237 },
       
   133     { "icirc",      238 },
       
   134     { "igrave",     236 },
       
   135     { "iota",       953 },
       
   136     { "iuml",       239 },
       
   137     { "kappa",      954 },
       
   138     { "lArr",       8656 },
       
   139     { "lambda",     955 },
       
   140     { "larr",       8592 },
       
   141     { "mu",         956 },
       
   142     { "ntilde",     241 },
       
   143     { "nu",         957 },
       
   144     { "oacute",     243 },
       
   145     { "ocirc",      244 },
       
   146     { "oelig",      339 },
       
   147     { "ograve",     242 },
       
   148     { "omega",      969 },
       
   149     { "omicron",    959 },
       
   150     { "oslash",     248 },
       
   151     { "otilde",     245 },
       
   152     { "otimes",     8855 },
       
   153     { "ouml",       246 },
       
   154     { "phi",        966 },
       
   155     { "pi",         960 },
       
   156     { "psi",        968 },
       
   157     { "rArr",       8658 },
       
   158     { "rarr",       8594 },
       
   159     { "rho",        961 },
       
   160     { "scaron",     353 },
       
   161     { "sigma",      963 },
       
   162     { "tau",        964 },
       
   163     { "theta",      952 },
       
   164     { "thorn",      254 },
       
   165     { "uArr",       8657 },
       
   166     { "uacute",     250 },
       
   167     { "uarr",       8593 },
       
   168     { "ucirc",      251 },
       
   169     { "ugrave",     249 },
       
   170     { "upsilon",    965 },
       
   171     { "uuml",       252 },
       
   172     { "xi",         958 },
       
   173     { "yacute",     253 },
       
   174     { "yuml",       255 },
       
   175     { "zeta",       950 },
       
   176     { "zwj",        8205 },
       
   177     { "zwnj",       8204 },
       
   178 // Case Insensitive entries
       
   179     { "alefsym",    8501 },
       
   180     { "amp",        38 },
       
   181     { "and",        8743 },
       
   182     { "ang",        8736 },
       
   183     { "apos",       39 },
       
   184     { "aring",      229 },
       
   185     { "asymp",      8776 },
       
   186     { "bdquo",      8222 },
       
   187     { "brvbar",     166 },
       
   188     { "bull",       8226 },
       
   189     { "cap",        8745 },
       
   190     { "cedil",      184 },
       
   191     { "cent",       162 },
       
   192     { "circ",       710 },
       
   193     { "clubs",      9827 },
       
   194     { "cong",       8773 },
       
   195     { "copy",       169 },
       
   196     { "crarr",      8629 },
       
   197     { "cup",        8746 },
       
   198     { "curren",     164 },
       
   199     { "deg",        176 },
       
   200     { "diams",      9830 },
       
   201     { "divide",     247 },
       
   202     { "empty",      8709 },
       
   203     { "emsp",       8195 },
       
   204     { "ensp",       8194 },
       
   205     { "equiv",      8801 },
       
   206     { "eth",        240 },
       
   207     { "euro",       8364 },
       
   208     { "exist",      8707 },
       
   209     { "fnof",       402 },
       
   210     { "forall",     8704 },
       
   211     { "frac12",     189 },
       
   212     { "frac14",     188 },
       
   213     { "frac34",     190 },
       
   214     { "frasl",      8260 },
       
   215     { "ge",         8805 },
       
   216     { "gt",         62 },
       
   217     { "hearts",     9829 },
       
   218     { "hellip",     8230 },
       
   219     { "iexcl",      161 },
       
   220     { "image",      8465 },
       
   221     { "infin",      8734 },
       
   222     { "int",        8747 },
       
   223     { "iquest",     191 },
       
   224     { "isin",       8712 },
       
   225     { "lang",       9001 },
       
   226     { "laquo",      171 },
       
   227     { "lceil",      8968 },
       
   228     { "ldquo",      8220 },
       
   229     { "le",         8804 },
       
   230     { "lfloor",     8970 },
       
   231     { "lowast",     8727 },
       
   232     { "loz",        9674 },
       
   233     { "lrm",        8206 },
       
   234     { "lsaquo",     8249 },
       
   235     { "lsquo",      8216 },
       
   236     { "lt",         60 },
       
   237     { "macr",       175 },
       
   238     { "mdash",      8212 },
       
   239     { "micro",      181 },
       
   240     { "middot",     183 },
       
   241     { "minus",      8722 },
       
   242     { "nabla",      8711 },
       
   243     { "nbsp",       160 },
       
   244     { "ndash",      8211 },
       
   245     { "ne",         8800 },
       
   246     { "ni",         8715 },
       
   247     { "not",        172 },
       
   248     { "notin",      8713 },
       
   249     { "nsub",       8836 },
       
   250     { "oline",      8254 },
       
   251     { "oplus",      8853 },
       
   252     { "or",         8744 },
       
   253     { "ordf",       170 },
       
   254     { "ordm",       186 },
       
   255     { "para",       182 },
       
   256     { "part",       8706 },
       
   257     { "permil",     8240 },
       
   258     { "perp",       8869 },
       
   259     { "piv",        982 },
       
   260     { "plusmn",     177 },
       
   261     { "pound",      163 },
       
   262     { "prime",      8242 },
       
   263     { "prod",       8719 },
       
   264     { "prop",       8733 },
       
   265     { "quot",       34 },
       
   266     { "radic",      8730 },
       
   267     { "rang",       9002 },
       
   268     { "raquo",      187 },
       
   269     { "rceil",      8969 },
       
   270     { "rdquo",      8221 },
       
   271     { "real",       8476 },
       
   272     { "reg",        174 },
       
   273     { "rfloor",     8971 },
       
   274     { "rlm",        8207 },
       
   275     { "rsaquo",     8250 },
       
   276     { "rsquo",      8217 },
       
   277     { "sbquo",      8218 },
       
   278     { "sdot",       8901 },
       
   279     { "sect",       167 },
       
   280     { "shy",        173 },
       
   281     { "sigmaf",     962 },
       
   282     { "sim",        8764 },
       
   283     { "spades",     9824 },
       
   284     { "sub",        8834 },
       
   285     { "sube",       8838 },
       
   286     { "sum",        8721 },
       
   287     { "sup",        8835 },
       
   288     { "sup1",       185 },
       
   289     { "sup2",       178 },
       
   290     { "sup3",       179 },
       
   291     { "supe",       8839 },
       
   292     { "szlig",      223 },
       
   293     { "there4",     8756 },
       
   294     { "thetasym",   977 },
       
   295     { "thinsp",     8201 },
       
   296     { "tilde",      732 },
       
   297     { "times",      215 },
       
   298     { "trade",      8482 },
       
   299     { "uml",        168 },
       
   300     { "upsih",      978 },
       
   301     { "weierp",     8472 },
       
   302     { "yen",        165 },
       
   303     { "zwj",        8205 },
       
   304     { "zwnj",       8204 },
       
   305     };
       
   306 
       
   307 
       
   308 // -----------------------------------------------------------------------------
       
   309 // CXmlEntity::NewL
       
   310 //
       
   311 // Two-phased constructor.
       
   312 // -----------------------------------------------------------------------------
       
   313 //
       
   314 CXmlEntity* CXmlEntity::NewL()
       
   315     {
       
   316     CXmlEntity* self = new (ELeave) CXmlEntity();
       
   317     
       
   318     CleanupStack::PushL(self);
       
   319     self->ConstructL();
       
   320     CleanupStack::Pop();
       
   321 
       
   322     return self;
       
   323     }
       
   324 
       
   325         
       
   326 // -----------------------------------------------------------------------------
       
   327 // CXmlEntity::CXmlEntity
       
   328 //
       
   329 // C++ default constructor can NOT contain any code, that
       
   330 // might leave.
       
   331 // -----------------------------------------------------------------------------
       
   332 //
       
   333 CXmlEntity::CXmlEntity():
       
   334         iLeakTracker(CLeakTracker::EXmlEntity), iEntityMappings(15)
       
   335     {
       
   336     }
       
   337         
       
   338 
       
   339 // -----------------------------------------------------------------------------
       
   340 // CXmlEntity::ConstructL
       
   341 //
       
   342 // Symbian 2nd phase constructor can leave.
       
   343 // -----------------------------------------------------------------------------
       
   344 //
       
   345 void CXmlEntity::ConstructL()
       
   346     {
       
   347     }
       
   348         
       
   349 
       
   350 // -----------------------------------------------------------------------------
       
   351 // CXmlEntity::~CXmlEntity
       
   352 //
       
   353 // Deconstructor.
       
   354 // -----------------------------------------------------------------------------
       
   355 //
       
   356 CXmlEntity::~CXmlEntity()
       
   357     {
       
   358     // Delete the cached encoding-map.
       
   359     for (TInt i = 0; i < iEntityMappings.Count(); i++)
       
   360         {
       
   361         xmlFree(iEntityMappings[i].orig);
       
   362         }
       
   363 
       
   364     iEntityMappings.Close();
       
   365     }
       
   366 
       
   367 
       
   368 // -----------------------------------------------------------------------------
       
   369 // CXmlEntity::ResolveL
       
   370 //
       
   371 // Resolves the named entity into its char-value.  Can handle numeric entities.
       
   372 // -----------------------------------------------------------------------------
       
   373 //
       
   374 void CXmlEntity::ResolveL(const TDesC& aName, TUint16& aUcs2Value)
       
   375     {
       
   376     HBufC8*   utf8 = NULL;
       
   377     xmlChar*  xmlStr = NULL;
       
   378 
       
   379     if (aName.Length() < 1)
       
   380         {
       
   381         User::Leave(KErrCorrupt);
       
   382         }
       
   383 
       
   384     // Resolve numeric entities...
       
   385     if (ResolveNumericL(aName, aUcs2Value))
       
   386         {
       
   387         return;
       
   388         }
       
   389 
       
   390     // Convert the name to utf8 -- its strdup'ed to zero-terminate it.
       
   391     utf8 = EscapeUtils::ConvertFromUnicodeToUtf8L(aName);
       
   392     CleanupStack::PushL(utf8);
       
   393     
       
   394     xmlStr = xmlStrndup(utf8->Ptr(), utf8->Size());
       
   395     User::LeaveIfNull(xmlStr);
       
   396     CleanupLibXml2::PushL(xmlStr);
       
   397     
       
   398     // Look up the entity in the static entity table.
       
   399     const CXmlEntity::EntityEntry& entity = LookupUsc2Value(xmlStr);
       
   400     aUcs2Value = entity.ucs2Value;
       
   401 
       
   402     // Clean up.
       
   403     CleanupStack::PopAndDestroy(/*xmlStr*/);
       
   404     CleanupStack::PopAndDestroy(utf8);
       
   405     }
       
   406 
       
   407 
       
   408 // -----------------------------------------------------------------------------
       
   409 // CXmlEntity::ResolveL
       
   410 //
       
   411 // Resolves the named entity into its EntityEntry.  Can NOT handle numeric entities.
       
   412 // -----------------------------------------------------------------------------
       
   413 //
       
   414 const xmlEntity* CXmlEntity::ResolveL(const xmlChar *aName)
       
   415     {
       
   416     TInt       index;
       
   417     xmlEntity  entity;
       
   418     
       
   419     // Init the entity.
       
   420     memset(&entity, 0x00, sizeof(xmlEntity));
       
   421 
       
   422     // Check if the entity has already been resolved.
       
   423     entity.name = aName;
       
   424     index = iEntityMappings.FindInOrder(entity, LinearOrder);
       
   425     
       
   426     if (index != KErrNotFound)
       
   427         {
       
   428         return &iEntityMappings[index];
       
   429         }
       
   430 
       
   431     // Also check if the entity has already been resolved in a case insensitive way.
       
   432     index = iEntityMappings.FindInOrder(entity, LinearCaseOrder);
       
   433     
       
   434     if (index != KErrNotFound)
       
   435         {
       
   436         return &iEntityMappings[index];
       
   437         }
       
   438 
       
   439     // Otherwise look it up in the static table, create a new entry and return it.
       
   440     TBuf<2>   ucs2;
       
   441     HBufC8*   utf8 = NULL;
       
   442     xmlChar*  utf8Value = NULL;
       
   443     
       
   444     // Get the entity as a ucs2 value from the static table.        
       
   445     const EntityEntry& entityEntry = LookupUsc2Value(aName);
       
   446             
       
   447     // Convert the value to utf8.
       
   448     ucs2.Append(entityEntry.ucs2Value);
       
   449     
       
   450     utf8 = EscapeUtils::ConvertFromUnicodeToUtf8L(ucs2);
       
   451     CleanupStack::PushL(utf8);
       
   452     
       
   453     utf8Value = xmlStrndup(utf8->Ptr(), utf8->Size());
       
   454     User::LeaveIfNull(utf8Value);
       
   455     CleanupLibXml2::PushL(utf8Value);
       
   456     
       
   457     // Populate the entity.
       
   458     entity.type = XML_ENTITY_DECL;
       
   459     entity.name = BAD_CAST(entityEntry.entityName);
       
   460     entity.orig = const_cast<xmlChar*>(utf8Value);
       
   461     entity.content = const_cast<xmlChar*>(utf8Value);
       
   462     entity.length = xmlStrlen(utf8Value);
       
   463     entity.etype = XML_INTERNAL_PREDEFINED_ENTITY;
       
   464 
       
   465     // Add the new entry.
       
   466     User::LeaveIfError(iEntityMappings.InsertInOrder(entity, LinearOrder));
       
   467     CleanupStack::Pop(/*utf8Value*/);
       
   468     CleanupStack::PopAndDestroy(utf8);
       
   469     
       
   470     // Return the newly added entry.
       
   471     index = iEntityMappings.FindInOrder(entity, LinearOrder);
       
   472 
       
   473     if (index == KErrNotFound)
       
   474         {
       
   475         User::Leave(KErrCorrupt);
       
   476         }
       
   477 
       
   478     return &iEntityMappings[index];
       
   479     }
       
   480 
       
   481 
       
   482 // -----------------------------------------------------------------------------
       
   483 // CXmlEntity::LookupUsc2Value
       
   484 //
       
   485 // Looks up the named entity in the static table.  Can NOT handle numeric entities.
       
   486 // -----------------------------------------------------------------------------
       
   487 //
       
   488 const CXmlEntity::EntityEntry& CXmlEntity::LookupUsc2Value(const xmlChar *aName)
       
   489     {
       
   490     TInt                index;
       
   491     const EntityEntry*  entry;
       
   492     TInt                low;
       
   493     TInt                high;
       
   494     TInt                res;
       
   495     TInt                numEntries;
       
   496 
       
   497     numEntries = (sizeof(sEntityMappings) / sizeof(EntityEntry));
       
   498 
       
   499     // First do a binary search search in the case sensitive part of the array.
       
   500     low = 0;
       
   501     high = numEntries - KNumCaseInsensitiveEntries - 1;
       
   502     res = 0;
       
   503 
       
   504     while (low <= high ) 
       
   505         {
       
   506         index = (high + low) / 2;
       
   507         entry = &(sEntityMappings[index]);
       
   508 
       
   509         // Do a case sensitive string comparison.
       
   510         res = xmlStrcmp(aName, BAD_CAST(entry->entityName));
       
   511 
       
   512         if (res > 0) 
       
   513             {
       
   514             /* name is ahead of this slot.  Increase low bound. */
       
   515             low = index + 1;
       
   516             } 
       
   517             
       
   518         else if (res < 0) 
       
   519             {
       
   520             /* name is behind this slot.  Decrease high bound. */
       
   521             high = index - 1;
       
   522             } 
       
   523         else 
       
   524             {
       
   525             /* Found the entity name.  Return its value. */
       
   526             return *entry;
       
   527             }
       
   528         }
       
   529 
       
   530     // If no match was found search in the case insensitive part of the table.
       
   531     low = numEntries - KNumCaseInsensitiveEntries;
       
   532     high = numEntries - 1;
       
   533     res = 0;
       
   534 
       
   535     while (low <= high ) 
       
   536         {
       
   537         index = (high + low) / 2;
       
   538         entry = &(sEntityMappings[index]);
       
   539 
       
   540         // Do a case insensitive string comparison.
       
   541         res = xmlStrcasecmp(aName, BAD_CAST(entry->entityName));
       
   542 
       
   543         if (res > 0) 
       
   544             {
       
   545             /* name is ahead of this slot.  Increase low bound. */
       
   546             low = index + 1;
       
   547             } 
       
   548             
       
   549         else if (res < 0) 
       
   550             {
       
   551             /* name is behind this slot.  Decrease high bound. */
       
   552             high = index - 1;
       
   553             } 
       
   554         else 
       
   555             {
       
   556             /* Found the entity name.  Return its value. */
       
   557             return *entry;
       
   558             }
       
   559         }
       
   560 
       
   561     // If no match were found return the space.
       
   562     return sSpaceEntity;
       
   563     }
       
   564 
       
   565 
       
   566 // -----------------------------------------------------------------------------
       
   567 // CXmlEntity::ResolveNumeric
       
   568 //
       
   569 // Resolves the numeric entity into it's value.
       
   570 // -----------------------------------------------------------------------------
       
   571 //
       
   572 TBool CXmlEntity::ResolveNumericL(const TDesC& aName, TUint16& aUcs2Value)
       
   573     {
       
   574     _LIT(KHash, "#");
       
   575     _LIT(KHex, "x");
       
   576     _LIT(KHEX, "X");
       
   577 
       
   578     TBool   found = EFalse;
       
   579 
       
   580     if (aName.Length() < 2)
       
   581         {
       
   582         return EFalse;
       
   583         }
       
   584 
       
   585 	if (aName.Left(1) == KHash)
       
   586 		{
       
   587         TRadix   aRadix = EDecimal;
       
   588         TPtrC    numeric;
       
   589 
       
   590         // Entity of the form, #x123
       
   591 		if ((aName.Mid(1, 1) == KHex) || (aName.Mid(1, 1) == KHEX))
       
   592 			{
       
   593 			numeric.Set(aName.Mid(2, aName.Length() - 2));
       
   594             aRadix = EHex;
       
   595 			}
       
   596 
       
   597         // Entity of the form, #123
       
   598 		else
       
   599 			{
       
   600 			numeric.Set(aName.Mid(1, aName.Length() - 1));
       
   601 			}
       
   602 
       
   603         // Convert the text into a ucs2 value.
       
   604         if (numeric.Length() > 0)
       
   605             {
       
   606 	        TLex  temp(numeric);
       
   607 
       
   608 	        temp.Val(aUcs2Value, aRadix);
       
   609 		    found = ETrue;
       
   610             }
       
   611 		}
       
   612 
       
   613     return found;
       
   614     }
       
   615 
       
   616 
       
   617 // -----------------------------------------------------------------------------
       
   618 // CXmlEntity::LinearOrder
       
   619 //
       
   620 // Comparison method for iEntityMappings.
       
   621 // -----------------------------------------------------------------------------
       
   622 //
       
   623 TInt CXmlEntity::LinearOrder(const xmlEntity& aFirst, const xmlEntity& aSecond)
       
   624     {
       
   625     return xmlStrcmp(aFirst.name, aSecond.name);
       
   626     }
       
   627 
       
   628 
       
   629 // -----------------------------------------------------------------------------
       
   630 // CXmlEntity::LinearCaseOrder
       
   631 //
       
   632 // Comparison method for iEntityMappings.
       
   633 // -----------------------------------------------------------------------------
       
   634 //
       
   635 TInt CXmlEntity::LinearCaseOrder(const xmlEntity& aFirst, const xmlEntity& aSecond)
       
   636     {
       
   637     return xmlStrcasecmp(aFirst.name, aSecond.name);
       
   638     }
       
   639