xml/xmldomandxpath/src/xmlenginedom/xmlengelement.cpp
changeset 0 e35f40988205
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Methods for element node
       
    15 //
       
    16 
       
    17 #include <xml/dom/xmlengelement.h>
       
    18 #include <xml/dom/xmlengdocument.h>
       
    19 #include <xml/dom/xmlengnamespace.h>
       
    20 #include <xml/dom/xmlengattr.h>
       
    21 #include <xml/dom/xmlengnodelist.h>
       
    22 #include <stdapis/libxml2/libxml2_globals.h>
       
    23 #include "xmlengdomdefs.h"
       
    24 #include <xml/utils/xmlengutils.h>
       
    25 #include <stdapis/libxml2/libxml2_parserinternals.h>
       
    26 #include <xml/utils/xmlengmem.h>
       
    27 #include <xml/utils/xmlengxestrings.h>
       
    28 #include "libxml2_tree_private.h"
       
    29 
       
    30 #define LIBXML_ELEMENT (static_cast<xmlNodePtr>(iInternal))
       
    31 
       
    32 void ResetNs(xmlNodePtr node,xmlNsPtr ns)
       
    33     {
       
    34     if(node->ns == ns)
       
    35         {
       
    36         node->ns = NULL;
       
    37         }
       
    38     xmlNodePtr child = node->children;
       
    39     while (child)
       
    40         {
       
    41         if(child->type == XML_ELEMENT_NODE)
       
    42             {
       
    43             ResetNs(child,ns);
       
    44             }
       
    45         child = child->next;
       
    46         }
       
    47     xmlAttrPtr attr = node->properties;
       
    48     while (attr)
       
    49         {
       
    50         if(attr->type == XML_ATTRIBUTE_NODE && attr->ns == ns)
       
    51             {
       
    52             attr->ns = NULL;
       
    53             }
       
    54         attr = attr->next;
       
    55         }
       
    56     };
       
    57 
       
    58 // ---------------------------------------------------------------------------------------------
       
    59 // Creates new attribute node out of any namespace (i.e. it has no prefix),
       
    60 // sets attribute's value and links it as the last attribute of the current element
       
    61 //   
       
    62 // @param  aName   A local name of attribute
       
    63 // @param  aValue  Value to set for new attribute or NULL (sets value to "")
       
    64 // @return         A handler to the newly created attribute node;
       
    65 //
       
    66 // For adding attribute as the first one, use TXmlEngNode::SetAsFirstSibling() on the attribute:
       
    67 // @code
       
    68 //     TXmlEngElement el = ... ; // get some element
       
    69 //     el.AddNewAttributeL("version","0.1").SetAsFirstSibling();
       
    70 // @endcode
       
    71 //   
       
    72 //   @see   SetAsLastSibling(), MoveBeforeSibling(TXmlEngNode) and MoveAfterSibling(TXmlEngNode)
       
    73 //
       
    74 //   @note   - No checks are made that attribute with such name exists
       
    75 //             Use this method only on newly created elements!
       
    76 //             Otherwise, use TXmlEngElement::SetAttributeL(..)
       
    77 //           - Attributes do not inherit default namespace of its element
       
    78 //             (http://w3.org/TR/REC-xml-names/#defaulting)
       
    79 //           - attribute's value is the second argument in all AddNewAttributeL(..) methods
       
    80 // ---------------------------------------------------------------------------------------------
       
    81 //
       
    82 EXPORT_C TXmlEngAttr TXmlEngElement::AddNewAttributeL(
       
    83     const TDesC8& aName,
       
    84     const TDesC8& aValue )
       
    85     {
       
    86     if ( !iInternal )
       
    87     	{
       
    88     	User::Leave(KXmlEngErrNullNode);
       
    89     	}
       
    90     if ( aName.Length() <= 0 ) 
       
    91     	{
       
    92     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
    93     	}
       
    94     //
       
    95     xmlChar* name = xmlCharFromDesC8L(aName);
       
    96     CleanupStack::PushL(name);
       
    97     xmlChar* value = xmlCharFromDesC8L(aValue);
       
    98     xmlAttrPtr attr = xmlNewProp( // NOTE: no checks that such attribute already exists
       
    99                             LIBXML_ELEMENT,
       
   100                             name,
       
   101                             value);
       
   102     delete value;
       
   103     CleanupStack::PopAndDestroy(name);
       
   104     OOM_IF_NULL(attr);
       
   105     return TXmlEngNode(attr).AsAttr();
       
   106     }
       
   107 
       
   108 // ---------------------------------------------------------------------------------------------
       
   109 // Creates new attribute node and add it to the element
       
   110 //
       
   111 // Provided handle to namespace declaration is used to set up
       
   112 // attribute's namespace.
       
   113 //
       
   114 // @note If aNsDef is not defined in some of attributes ascendants
       
   115 //     (including this element), then
       
   116 //      ReconcileNamespacesL() method must be called on
       
   117 //      this element later.
       
   118 // ---------------------------------------------------------------------------------------------
       
   119 //
       
   120 EXPORT_C TXmlEngAttr  TXmlEngElement::AddNewAttributeL(
       
   121     const TDesC8& aName,
       
   122     const TDesC8& aValue,
       
   123     TXmlEngNamespace aNsDef)
       
   124     {
       
   125     TXmlEngAttr attr = AddNewAttributeL(aName, aValue);
       
   126     
       
   127     _LIT(KAutoPrefix,"_pr%d");
       
   128     const TInt KMaxPrefLength = 20;
       
   129     TBuf<KMaxPrefLength> prefix;
       
   130     
       
   131     TUint ind = 0;
       
   132     char* prefCh = NULL;
       
   133     xmlNsPtr ns;
       
   134     
       
   135     if (aNsDef.NotNull())
       
   136         {
       
   137         if (aNsDef.IsDefault())
       
   138             {
       
   139             // create new temporary namespace binding (with non-NULL prefix)
       
   140             ns = NULL;
       
   141             while(!ns)
       
   142                 {
       
   143                 // generate prefix
       
   144                 ++ind;
       
   145                 prefix.Format(KAutoPrefix,ind);
       
   146                 prefCh = XmlEngXmlCharFromDesL(prefix);
       
   147                 TXmlEngConstString pref(prefCh);
       
   148                 delete prefCh;
       
   149         		
       
   150         		if(!xmlSearchNs(LIBXML_ELEMENT->doc,
       
   151 	        					LIBXML_ELEMENT,
       
   152 	        					CAST_DOMSTRING_TO_XMLCHAR(pref)))
       
   153         			{
       
   154 	                ns = xmlNewNs(
       
   155 	                        LIBXML_ELEMENT,
       
   156 	                        INTERNAL_NSPTR(aNsDef)->href,
       
   157 	                        CAST_DOMSTRING_TO_XMLCHAR(pref));
       
   158 	                TEST_OOM_FLAG;        			
       
   159         			}
       
   160                 }
       
   161             }
       
   162         else
       
   163             {
       
   164             ns = INTERNAL_NSPTR(aNsDef);
       
   165             }
       
   166         INTERNAL_ATTRPTR(attr)->ns = ns;
       
   167         }
       
   168     return attr;
       
   169     }
       
   170 
       
   171 // ---------------------------------------------------------------------------------------------
       
   172 // Creates new attribute on the element. Namespace declaration for the attribute namespace is
       
   173 // created too.
       
   174 //
       
   175 // @note
       
   176 //     - Namespace declarations are reused if possible (no redundant ones are created)
       
   177 // ---------------------------------------------------------------------------------------------
       
   178 //
       
   179 EXPORT_C TXmlEngAttr TXmlEngElement::AddNewAttributeL(
       
   180     const TDesC8& aName,
       
   181     const TDesC8& aValue,
       
   182     const TDesC8& aNsUri,
       
   183     const TDesC8& aPrefix )
       
   184     {
       
   185     TXmlEngAttr attr = AddNewAttributeL(aName, aValue);
       
   186     
       
   187     if (!aPrefix.Length()) // NULL or "" 	 
       
   188         {	  	 
       
   189         if (aNsUri.Length()) // !(NULL or "") --> namespace URI is present
       
   190             {
       
   191             // An attribute cannot have default namespace (Pref = "" AND nsUri!="")
       
   192 	        WRONG_USE_OF_API;
       
   193             }	  	 
       
   194         return attr; 	  	  	 
       
   195         }
       
   196     
       
   197     TXmlEngNamespace nsDef = AddNamespaceDeclarationL(aNsUri, aPrefix);
       
   198     INTERNAL_ATTRPTR(attr)->ns = INTERNAL_NSPTR(nsDef);
       
   199     return attr;
       
   200     }
       
   201 
       
   202 // ---------------------------------------------------------------------------------------------
       
   203 // Creates new attributes using namespace, which is bound to the specified prefix
       
   204 //
       
   205 // Please, use this mothod only for construction of new parts of DOM tree, where
       
   206 // you know for sure that prefix is bound in the given scope.
       
   207 // @code
       
   208 //     TXmlEngElement el = parent.AddNewAttributeUsePrefixL("property","ObjName","rdf");
       
   209 //     el.AddNewAttributeUsePrefixL("type", "xs:integer", "rdf");
       
   210 // @endcode
       
   211 //
       
   212 // Otherwise, you should check that prefix is bound like this example shows:
       
   213 // @code
       
   214 //     TXmlEngNamespace boundNS = TXmlEngNamespace::LookupByPrefix(thisElement, prefix);
       
   215 //     if (boundNS.NotNull()){
       
   216 //         thisElement.AddNewAttributeUsePrefixL("name", value, prefix);
       
   217 //     }
       
   218 // @endcode
       
   219 //
       
   220 // @note
       
   221 //     Use AddNewAttributeNsL(name,value,nsDefNode) as much as you can, because
       
   222 //     it is most efficient way to create namespaced DOM elements (no additional
       
   223 //     lookups for namespace declarations are required).
       
   224 //   
       
   225 // @code
       
   226 //     // If namespace with given URI is not in the scope, then it will be declared
       
   227 //     // and bound to "data" prefix.
       
   228 //     TXmlEngNamespace nsDef = elem.FindOrCreateNsDeclL("http://../Data", "data");
       
   229 //     elem.AddNewAttributeL("location", "...", nsDef);
       
   230 //     elem.AddNewElementL("child", nsDef).AddNewAttributeL("attr","...value...");
       
   231 //     // the result is
       
   232 //        ...
       
   233 //        <elem xmlns:data="http://../Data" data:location="...">
       
   234 //           <data:child attr="...value..."/>
       
   235 //        </elem>
       
   236 //        ...
       
   237 //     //
       
   238 // @endcode    
       
   239 // ---------------------------------------------------------------------------------------------
       
   240 //
       
   241 EXPORT_C TXmlEngAttr TXmlEngElement::AddNewAttributeUsePrefixL(
       
   242     const TDesC8& aLocalName,
       
   243     const TDesC8& aValue,
       
   244     const TDesC8& aPrefix )
       
   245     {
       
   246     _LIT8(KXml,"xml");
       
   247     TXmlEngAttr attr = AddNewAttributeL(aLocalName, aValue);
       
   248     // try to locate namespace binding for the same prefix
       
   249     xmlChar* prefix = xmlCharFromDesC8L(aPrefix);
       
   250     xmlNsPtr ns = xmlSearchNs(
       
   251                     LIBXML_ELEMENT->doc,
       
   252                     LIBXML_ELEMENT,
       
   253                     prefix);
       
   254     delete prefix;                
       
   255     
       
   256     if (!ns)
       
   257         {
       
   258         // OOM may happen ONLY for "xml" prefix search
       
   259         OOM_IF(!aPrefix.Compare(KXml));
       
   260         WRONG_USE_OF_API; // Prefix is not bound
       
   261         }
       
   262     INTERNAL_ATTRPTR(attr)->ns = ns;
       
   263     return attr;
       
   264 }
       
   265 
       
   266 // ---------------------------------------------------------------------------------------------
       
   267 // Creates new attributes using namespace in the scope, which has specified URI
       
   268 //   
       
   269 // Almost the same as AddNewAttributeUsePrefixL(...) but does lookup by namespace URI
       
   270 //
       
   271 // @return - NULL attribute if namespace declaration is not found OR newly added to the end of
       
   272 //     attribute list attribute of this element.
       
   273 //
       
   274 // @see AddNewAttributeUsePrefixL(TDesC8,TDesC8,TDesC8)
       
   275 // ---------------------------------------------------------------------------------------------
       
   276 //
       
   277 EXPORT_C TXmlEngAttr TXmlEngElement::AddNewAttributeWithNsL(
       
   278     const TDesC8& aLocalName,
       
   279     const TDesC8& aValue,
       
   280     const TDesC8& aNsUri )
       
   281     {
       
   282     _LIT8(KXmlNs,"http://www.w3.org/XML/1998/namespace");
       
   283     // try to locate namespace binding for the same prefix
       
   284     xmlChar* nsp = xmlCharFromDesC8L(aNsUri);
       
   285     xmlNsPtr ns = xmlSearchNsByHref(
       
   286                     LIBXML_ELEMENT->doc,
       
   287                     LIBXML_ELEMENT,
       
   288                     nsp);
       
   289     delete nsp;
       
   290     
       
   291     if (!ns)
       
   292         {
       
   293         // OOM may happen ONLY for "xml" prefix search
       
   294         OOM_IF(!aNsUri.Compare(KXmlNs));
       
   295         TXmlEngAttr attr;
       
   296         return attr;
       
   297         }
       
   298     
       
   299     TXmlEngAttr attr = AddNewAttributeL(aLocalName, aValue);
       
   300         
       
   301     INTERNAL_ATTRPTR(attr)->ns = ns;
       
   302     return attr;
       
   303     }
       
   304 
       
   305 // ---------------------------------------------------------------------------------------------
       
   306 // Adds child element with no namespace
       
   307 //
       
   308 // @param aName name of the element
       
   309 //
       
   310 // Results in adding element with aName and no prefix.
       
   311 //
       
   312 // This method is the best for creation of non-namespace based documents
       
   313 // or document fragments, where no default namespace declared.
       
   314 //
       
   315 // It may be used also as a method for  adding element from default namespace,
       
   316 // BUT namespace will be assigned ONLY after serialization of the current
       
   317 // document and parsing it back into a DOM tree!! If you need that default namespace
       
   318 // was inherited by new element immediately use:
       
   319 // @code
       
   320 //     ...
       
   321 //     TXmlEngNamespace defns = element.DefaultNamespace();
       
   322 //     TXmlEngElement newEl = element.AddNewElementL("Name",defns);
       
   323 //     ...
       
   324 // @endcode
       
   325 //
       
   326 // If truly undefined namespace for the element is required, then <b>DO NOT USE</b>
       
   327 // this method if there is a default namespace in the scope!
       
   328 // ---------------------------------------------------------------------------------------------
       
   329 //
       
   330 EXPORT_C TXmlEngElement TXmlEngElement::AddNewElementL(
       
   331     const TDesC8& aName )
       
   332     {
       
   333     if ( !iInternal )
       
   334     	{
       
   335     	User::Leave(KXmlEngErrNullNode);
       
   336     	}
       
   337     if ( aName.Length() <= 0 ) 
       
   338     	{
       
   339     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   340     	}
       
   341     xmlChar* name = xmlCharFromDesC8L(aName);
       
   342     xmlNodePtr element = xmlNewNode(NULL, name);
       
   343     delete name;
       
   344     //
       
   345     OOM_IF_NULL(element);
       
   346     //
       
   347     element->parent = LIBXML_ELEMENT;
       
   348     element->doc = LIBXML_ELEMENT->doc;
       
   349     // Link element as the last child
       
   350     xmlNodePtr prev = LIBXML_ELEMENT->last;
       
   351     LIBXML_ELEMENT->last = element;
       
   352     element->prev = prev;
       
   353     if (prev)
       
   354         {
       
   355         prev->next = element;
       
   356         }
       
   357     if (!(LIBXML_ELEMENT->children))
       
   358         {
       
   359         LIBXML_ELEMENT->children = element;
       
   360         }
       
   361     return TXmlEngElement(element);
       
   362     }
       
   363 
       
   364 // ---------------------------------------------------------------------------------------------
       
   365 // Creates new child element with provided name, prefix and namespace URI
       
   366 //
       
   367 // New namespace declaration will be attached to the parent (this) element and used
       
   368 // as namespace for newly created child element. If such binding already exists
       
   369 // (same prefix is bound to same URI), it will be reused. If the prefix is already
       
   370 // bound to some another namespace URI, it will be rebound by the new namespace
       
   371 // declaration node.
       
   372 //
       
   373 // @param aLocalName Name of the element
       
   374 // @param aNsUri     URI of element's namespace
       
   375 // @param aPrefix    Prefix of the element
       
   376 // @return Created element node (and added as the last child of its parent)
       
   377 // ---------------------------------------------------------------------------------------------
       
   378 //
       
   379 EXPORT_C TXmlEngElement TXmlEngElement::AddNewElementL(
       
   380     const TDesC8& aLocalName,
       
   381     const TDesC8& aNsUri,
       
   382     const TDesC8& aPrefix )
       
   383     {
       
   384     TXmlEngElement element = AddNewElementL(aLocalName);
       
   385     TXmlEngNamespace nsDef = AddNamespaceDeclarationL(aNsUri, aPrefix);
       
   386     INTERNAL_NODEPTR(element)->ns = INTERNAL_NSPTR(nsDef);
       
   387     return element;
       
   388     }
       
   389 
       
   390 // ---------------------------------------------------------------------------------------------
       
   391 // Creates new child element with provided name and namespace declaration
       
   392 //
       
   393 // @param aLocalName Name of the element
       
   394 // @param aNsDef     Handle of the namespace declaration, that must be retrieved from
       
   395 //                  one of the ascendant nodes of the new elements (and its prefix
       
   396 //                  should not be remapped to another namespace URI for the scope
       
   397 //                  of the new element)
       
   398 // @return    Created element node (and added as the last child of its parent)
       
   399 // ---------------------------------------------------------------------------------------------
       
   400 //
       
   401 EXPORT_C TXmlEngElement  TXmlEngElement::AddNewElementL(
       
   402     const TDesC8& aLocalName,
       
   403     TXmlEngNamespace aNsDef )
       
   404     {
       
   405     TXmlEngElement element = AddNewElementL(aLocalName);
       
   406     INTERNAL_NODEPTR(element)->ns = INTERNAL_NSPTR(aNsDef);
       
   407     return element;
       
   408     }
       
   409 
       
   410 // ---------------------------------------------------------------------------------------------
       
   411 // Adds child element with same namespace (and prefix if present) as parent element has
       
   412 //
       
   413 // @param aLocalName element's name
       
   414 // @return New element that was added to the end of children list of its parent (this element)
       
   415 // ---------------------------------------------------------------------------------------------
       
   416 //
       
   417 EXPORT_C TXmlEngElement TXmlEngElement::AddNewElementSameNsL(
       
   418     const TDesC8& aLocalName )
       
   419     {
       
   420     TXmlEngElement element = AddNewElementL(aLocalName);
       
   421     INTERNAL_NODEPTR(element)->ns = LIBXML_ELEMENT->ns;
       
   422     return element;
       
   423     }
       
   424 
       
   425 // ---------------------------------------------------------------------------------------------
       
   426 // Performs lookup for the namespace declaration for specified prefix and
       
   427 // adds new child element with found namespace.
       
   428 //
       
   429 // The assumption is that prefix is bound, otherwise run-time error
       
   430 // (Symbian's Leave or exception) occurs
       
   431 //
       
   432 // @note   Use this method only if there is a binding for the given prefix.
       
   433 //
       
   434 // @param aLocalName element's name
       
   435 // @param aPrefix    prefix to use
       
   436 // @return new TXmlEngElement that was added to the end of children list of its parent (this element)
       
   437 // ---------------------------------------------------------------------------------------------
       
   438 //
       
   439 EXPORT_C TXmlEngElement TXmlEngElement::AddNewElementUsePrefixL(
       
   440     const TDesC8& aLocalName,
       
   441     const TDesC8& aPrefix )
       
   442     {
       
   443     _LIT8(KXml,"xml");
       
   444     TXmlEngElement element = AddNewElementL(aLocalName);
       
   445     // Can fail only with XML's namespace
       
   446     xmlChar* pref = xmlCharFromDesC8L(aPrefix);
       
   447     xmlNsPtr ns = xmlSearchNs(
       
   448                     LIBXML_ELEMENT->doc,
       
   449                     LIBXML_ELEMENT,
       
   450                     pref);
       
   451     delete pref;
       
   452     //
       
   453     OOM_IF(!ns && !aPrefix.Compare(KXml));
       
   454     //
       
   455     INTERNAL_NODEPTR(element)->ns = ns;
       
   456     return element;
       
   457     }
       
   458 
       
   459 // ---------------------------------------------------------------------------------------------
       
   460 // Performs lookup for the namespace declaration for specified namespace URI and
       
   461 // adds new child element with found namespace.
       
   462 //
       
   463 // The assumption is that namespace with given URI was declared,
       
   464 // otherwise run-time error (Symbian' Leave or exception) occurs
       
   465 //
       
   466 // @note Use this method only if namespace declaration for the provided URI exists.
       
   467 //
       
   468 // @param aLocalName element's name
       
   469 // @param aNsUri     namespace of element
       
   470 // @return new TXmlEngElement that was added to the end of children list of its parent (this element)
       
   471 // ---------------------------------------------------------------------------------------------
       
   472 //
       
   473 EXPORT_C TXmlEngElement TXmlEngElement::AddNewElementWithNsL(
       
   474     const TDesC8& aLocalName,
       
   475     const TDesC8& aNsUri )
       
   476     {
       
   477     _LIT8(KXmlNs,"http://www.w3.org/XML/1998/namespace");
       
   478     TXmlEngElement element = AddNewElementL(aLocalName);
       
   479     /*xmlNsPtr ns = xmlSearchNsByHref(
       
   480                     LIBXML_ELEMENT->doc,
       
   481                     LIBXML_ELEMENT,
       
   482                     CAST_DOMSTRING_TO_XMLCHAR(aNsUri));
       
   483     */
       
   484     TXmlEngNamespace ns = LookupNamespaceByUriL(aNsUri);
       
   485     // May fail only with XML's namespace
       
   486     OOM_IF(ns.IsNull() && !aNsUri.Compare(KXmlNs));
       
   487     //
       
   488     INTERNAL_NODEPTR(element)->ns = INTERNAL_NSPTR(ns);
       
   489     return element;
       
   490     }
       
   491 
       
   492 // ---------------------------------------------------------------------------------------------
       
   493 // Creates new child element; if there is no a prefix binding for new element's namespace,
       
   494 // a namespace decaration is created with generated prefix at specified element.
       
   495 //
       
   496 // @param aLocalName    Name of the element to create
       
   497 // @param aNsUri        Namespace URI of the new element
       
   498 // @param aNsDeclTarget An element where namespace declaraton should be placed
       
   499 //                     if there is a needed to create new namespace declaration;
       
   500 //                     NULL is used to specify the created element itself
       
   501 //
       
   502 // As aNsDeclTarget any ascendant of the new node may be provided:
       
   503 // @code
       
   504 //     el.AddNewElementAutoPrefixL(tagName,uri,NULL); // declare on the new element
       
   505 //     el.AddNewElementAutoPrefixL(tagName,uri,el);   // declare on the parent element
       
   506 //     el.AddNewElementAutoPrefixL(tagName,uri,doc.DocumentElement()); // declare on the root element
       
   507 //     ...
       
   508 // @endcode
       
   509 //
       
   510 // @note
       
   511 //     The farther namespace declaration up in the document tree,
       
   512 //     the longer time namespace declaration lookups take.
       
   513 // ---------------------------------------------------------------------------------------------
       
   514 //
       
   515 EXPORT_C TXmlEngElement TXmlEngElement::AddNewElementAutoPrefixL(
       
   516     const TDesC8& aLocalName,
       
   517     const TDesC8& aNsUri,
       
   518     TXmlEngElement aNsDeclTarget )
       
   519     {
       
   520     TXmlEngElement elem = AddNewElementL(aLocalName);
       
   521     if (aNsDeclTarget.IsNull())
       
   522         aNsDeclTarget = elem;
       
   523     TXmlEngNamespace ns = aNsDeclTarget.FindOrCreateNsDeclL(aNsUri);
       
   524     INTERNAL_NODEPTR(elem)->ns = INTERNAL_NSPTR(ns);
       
   525     return elem;
       
   526     }
       
   527 
       
   528 // ---------------------------------------------------------------------------------------------
       
   529 // Retrieves list of attribute nodes of the element
       
   530 //   
       
   531 // @param aList - a node list object to initialize
       
   532 //
       
   533 // Passed by reference list of nodes is initialized and after call to
       
   534 // Attributes(..) is ready for use with HasNext() and Next() methods:
       
   535 //
       
   536 // @code
       
   537 //     ...
       
   538 //     TXmlEngElement root = doc.DocumentElement();
       
   539 //     TXmlEngNodeList<TXmlEngAttr>    attlist;
       
   540 //     root.GetAttributes(attlist);
       
   541 //     while (attlist.HasNext())
       
   542 //           processAttribute(attlist.Next());
       
   543 //     ...
       
   544 // @endcode
       
   545 // ---------------------------------------------------------------------------------------------
       
   546 //
       
   547 EXPORT_C void TXmlEngElement::GetAttributes(
       
   548     RXmlEngNodeList<TXmlEngAttr>& aList ) const
       
   549     {
       
   550     //pjj18
       
   551     aList.Open( LIBXML_ELEMENT->properties,
       
   552                   TXmlEngNode::EAttribute);
       
   553     }
       
   554 
       
   555 // ---------------------------------------------------------------------------------------------
       
   556 // Retrieves list of child elements of the element
       
   557 //
       
   558 // @param aList - a node list object to initialize
       
   559 //
       
   560 // Passed by reference list of nodes is initialized and after the call
       
   561 // it is ready for use with HasNext() and Next() methods:
       
   562 //   
       
   563 // @note Returned list is a "filtered view" of the underlying
       
   564 //     list of all element's children (with text nodes, comments
       
   565 //     processing instructions, etc.)
       
   566 // ---------------------------------------------------------------------------------------------
       
   567 //  
       
   568 EXPORT_C void TXmlEngElement::GetChildElements(
       
   569     RXmlEngNodeList<TXmlEngElement>& aList ) const
       
   570     {
       
   571     //pjj18
       
   572     aList.Open( LIBXML_ELEMENT->children,
       
   573                   TXmlEngNode::EElement);
       
   574     }
       
   575 
       
   576 // ---------------------------------------------------------------------------------------------
       
   577 // @return Basic contents of the element
       
   578 //
       
   579 // This method may be used in most cases, when element has only simple text content
       
   580 // (without entity references embedded)
       
   581 //
       
   582 // If element's contents is mixed (other types of nodes present), only contents of
       
   583 // first child node is returned if it is a TXmlEngTextNode node. For getting mixed contents of the
       
   584 // element of contents with entity references, WholeTextValueCopyL() should be used.
       
   585 //
       
   586 // @see TXmlEngNode::WholeTextContentsCopyL()
       
   587 // ---------------------------------------------------------------------------------------------
       
   588 //
       
   589 EXPORT_C TPtrC8 TXmlEngElement::Text() const
       
   590     {
       
   591     if (LIBXML_ELEMENT && LIBXML_ELEMENT->children && LIBXML_ELEMENT->children->type == XML_TEXT_NODE)
       
   592         {
       
   593         return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(LIBXML_ELEMENT->children->content)).PtrC8();
       
   594         }
       
   595     return KNullDesC8();
       
   596     }
       
   597 
       
   598 // ---------------------------------------------------------------------------------------------
       
   599 // Adds text as a child of the element.
       
   600 //
       
   601 // At the moment, content may be only added, replaced (set) and read from element.
       
   602 //
       
   603 // @param aString text to be added as element's content.
       
   604 //
       
   605 // @note There may be several TXmlEngTextNode and TXmlEngEntityReference nodes added actually,
       
   606 //      depending on the aString value
       
   607 // ---------------------------------------------------------------------------------------------
       
   608 //
       
   609 EXPORT_C void TXmlEngElement::AddTextL(
       
   610     const TDesC8& aString )
       
   611     {
       
   612     if ( !LIBXML_ELEMENT )
       
   613     	{
       
   614     	User::Leave(KXmlEngErrNullNode);
       
   615     	}
       
   616     //
       
   617     xmlNodePtr last, newNode, tmp;
       
   618     last = LIBXML_ELEMENT->last;
       
   619     xmlChar* text = xmlCharFromDesC8L(aString);
       
   620     newNode = xmlNewTextLen(NULL, aString.Size());
       
   621     if(!newNode)
       
   622         {
       
   623         delete text;
       
   624         OOM_HAPPENED;
       
   625         }
       
   626     newNode->content = text;
       
   627 
       
   628     tmp = xmlAddChild(LIBXML_ELEMENT, newNode);
       
   629     if (xmlOOMFlag())
       
   630         {
       
   631         xmlFreeNode(newNode);
       
   632         OOM_HAPPENED;
       
   633         }
       
   634 
       
   635     if (tmp == newNode &&
       
   636         last && last->next == newNode)
       
   637         {
       
   638         OOM_IF_NULL(xmlTextMerge(last, newNode));
       
   639         }
       
   640     }
       
   641 
       
   642 // ---------------------------------------------------------------------------------------------
       
   643 // Ad Xml:Id attribute to the element
       
   644 // ---------------------------------------------------------------------------------------------
       
   645 //
       
   646 EXPORT_C TXmlEngAttr TXmlEngElement::AddXmlIdL(const TDesC8& aLocalName,
       
   647                                    const TDesC8& aValue,
       
   648                                    TXmlEngNamespace aNs)
       
   649     {
       
   650     if(IsNull())
       
   651     	{
       
   652         User::Leave(KXmlEngErrWrongUseOfAPI);
       
   653     	}
       
   654     
       
   655     TXmlEngAttr attr;
       
   656     xmlChar* value = xmlCharFromDesC8L(aValue);
       
   657     xmlAttrPtr tmp = xmlGetID(LIBXML_ELEMENT->doc, value);
       
   658     if(tmp)
       
   659         {
       
   660         delete value;
       
   661         return attr;
       
   662         }
       
   663     
       
   664     attr = AddNewAttributeL(aLocalName, aValue);
       
   665     if(aNs.NotNull())
       
   666         {
       
   667         TXmlEngNamespace tmp = LookupNamespaceByPrefixL(aNs.Prefix());
       
   668         if(!tmp.IsSameNode(aNs))
       
   669             {
       
   670             attr.Remove();
       
   671             delete value;
       
   672             return attr;
       
   673             }
       
   674         INTERNAL_ATTRPTR(attr)->ns = INTERNAL_NSPTR(aNs);
       
   675         }
       
   676     
       
   677     if(attr.IsNull())
       
   678         {
       
   679         User::Leave(KXmlEngErrWrongUseOfAPI);
       
   680         }
       
   681         
       
   682     if(!xmlAddID(NULL, LIBXML_ELEMENT->doc, value, INTERNAL_ATTRPTR(attr)))
       
   683         {
       
   684         delete value;
       
   685         attr.Remove();
       
   686         XmlEngOOMTestL();
       
   687         }
       
   688     delete value;
       
   689     return attr;
       
   690     }
       
   691 
       
   692 // ---------------------------------------------------------------------------------------------
       
   693 // Sets text contents for the element.
       
   694 // Any child nodes are removed.
       
   695 // Same as TXmlEngNode::SetValueL(const TDesC8&)
       
   696 //
       
   697 // @see TXmlEngNode::SetValueL(const TDesC8&)
       
   698 // ---------------------------------------------------------------------------------------------
       
   699 //
       
   700 EXPORT_C void TXmlEngElement::SetTextL(const TDesC8& aString)
       
   701     {
       
   702     AsAttr().SetValueL(aString);
       
   703     }
       
   704 
       
   705 // ---------------------------------------------------------------------------------------------
       
   706 // Sets text content of the element from escaped string.
       
   707 // @see TXmlEngAttr::SetEscapedValueL(const TDesC8&)
       
   708 // ---------------------------------------------------------------------------------------------
       
   709 //
       
   710 EXPORT_C void TXmlEngElement::SetEscapedTextL(const TDesC8& aEscapedString)
       
   711     {
       
   712     AsAttr().SetEscapedValueL(aEscapedString);
       
   713     }
       
   714 
       
   715 
       
   716 // -------------------------------------------------------------------------------------
       
   717 // Sets new element value exactly as presented in the string.
       
   718 // Predefined entities are not converted into characters they represent.
       
   719 // Any child nodes are removed.
       
   720 // -------------------------------------------------------------------------------------
       
   721 //
       
   722 EXPORT_C void TXmlEngElement::SetTextNoEncL(const TDesC8& aNotEncString)
       
   723 	{
       
   724     AsAttr().SetValueNoEncL(aNotEncString);	
       
   725 	}
       
   726 
       
   727 // -------------------------------------------------------------------------------------
       
   728 // Appends new text node with the value exactly as presented in the string.
       
   729 // Predefined entities are not converted into characters they represent.
       
   730 // Child nodes are not removed.  
       
   731 // -------------------------------------------------------------------------------------
       
   732 //
       
   733 EXPORT_C void TXmlEngElement::AppendTextNoEncL(const TDesC8& aNotEncString)
       
   734 	{
       
   735     if ( !LIBXML_ELEMENT )
       
   736     	{
       
   737     	User::Leave(KXmlEngErrNullNode);
       
   738     	}
       
   739 
       
   740     xmlNodePtr prop = LIBXML_ELEMENT;
       
   741     xmlNodePtr new_ch;
       
   742 
       
   743 	if (aNotEncString.Length())
       
   744         {
       
   745 		xmlChar* value = xmlCharFromDesC8L(aNotEncString);
       
   746         new_ch = xmlNewText(NULL);
       
   747         if(!new_ch)
       
   748             {
       
   749             delete value;
       
   750             OOM_HAPPENED;
       
   751             };
       
   752 
       
   753         new_ch->name = xmlStringTextNoenc;
       
   754         new_ch->content = value;
       
   755         new_ch->parent = (xmlNodePtr) prop;
       
   756        	xmlNodePtr last = prop->last;
       
   757        	if(last)
       
   758        		{
       
   759        		last->next = new_ch;
       
   760        		new_ch->prev = last;
       
   761        		}
       
   762        	else
       
   763        		{
       
   764        		prop->children = new_ch;
       
   765        		}
       
   766        	prop->last = new_ch;
       
   767         }   
       
   768 	}
       
   769 	
       
   770 	
       
   771 // ---------------------------------------------------------------------------------------------
       
   772 // Adds default namespace declaration.
       
   773 //
       
   774 // @param aNsUri   Namespace URI;  both NULL and "" (empty string) are allowed to represent UNDEFINED NAMSPACE
       
   775 //
       
   776 // Same result as with AddNamespaceDeclarationL(aNsUri, NULL), but additionally
       
   777 // element's namespace modified (if it has no prefix and there were no default
       
   778 // namespace declaration in the scope) to the new default one.
       
   779 //
       
   780 // @return Handle to the created namespace declaration (NULL for UNDEFINED NAMESPACE)
       
   781 // ---------------------------------------------------------------------------------------------
       
   782 //
       
   783 EXPORT_C TXmlEngNamespace TXmlEngElement::SetDefaultNamespaceL(
       
   784     const TDesC8& aNsUri)
       
   785     {
       
   786     TXmlEngNamespace nsDef = AddNamespaceDeclarationL(aNsUri,KNullDesC8);
       
   787     if (!LIBXML_ELEMENT->ns)
       
   788         LIBXML_ELEMENT->ns = INTERNAL_NSPTR(nsDef);
       
   789     return nsDef;
       
   790     }
       
   791 
       
   792 // ---------------------------------------------------------------------------------------------
       
   793 // Undeclares any default namespace for current element and its descendants.
       
   794 //
       
   795 // If there is already some default namespace,  <i>xmlns=""</i> namespace
       
   796 // declaration is added. Otherwise, nothing happens, since element with no
       
   797 // prefix in such scope is automaticaly considered as out of any namespace.
       
   798 //
       
   799 // The side effect of this method is that namespace of the current element
       
   800 // may change from previous <b>default</b> namespace to NULL TXmlEngNamespace, which is
       
   801 // considered an absence of namespace.
       
   802 //
       
   803 // If the element has prefix (i.e. not having default namespace), 
       
   804 // then the only effect for the element is undeclaration of existing default namespace. 
       
   805 //
       
   806 // If element is in the scope of another <i>xmlns=""</i> undeclaration, no
       
   807 // actions are taken.
       
   808 //
       
   809 // @note
       
   810 //     Use AddNamespaceDeclarationL(NULL,NULL) to force creation of
       
   811 //     xmlns=""  declaration within scope of another such declaration 
       
   812 //     (otherwise unneccessary/duplicate declarations are not created)
       
   813 //
       
   814 // @note
       
   815 //     This method should be called on elements before adding children,
       
   816 //     because default namespace undeclaration is not spread into its subtree and 
       
   817 //     descedants' default namespaces are not reset to NULL. This should be taken into 
       
   818 //     account if later some processing on the subtree occurs.
       
   819 //     However, after serialization and deserialization, undeclared default namespace will
       
   820 //     affect whole element's subtree correctly.
       
   821 // ---------------------------------------------------------------------------------------------
       
   822 //
       
   823 EXPORT_C void TXmlEngElement::SetNoDefaultNamespaceL()
       
   824     {
       
   825     if ( !LIBXML_ELEMENT )
       
   826     	{
       
   827     	User::Leave(KXmlEngErrNullNode);
       
   828     	}
       
   829     //
       
   830     TXmlEngNamespace defns = LookupNamespaceByPrefixL(KNullDesC8);
       
   831     if (defns.IsUndefined()) // NULL or Uri is NULL
       
   832         {
       
   833         // we are already in the scope of xmlns="" , so do nothing
       
   834         return;
       
   835         }
       
   836 
       
   837     // There is some default namespace in the scope.
       
   838     // Add local "undefined" namespace and change element's namespace
       
   839     // if it is the default one
       
   840     AddNamespaceDeclarationL(KNullDesC8, KNullDesC8);
       
   841     TXmlEngNamespace myNs(LIBXML_ELEMENT->ns);
       
   842     if (myNs.IsDefault())
       
   843         {
       
   844         // replace default namespace with undefined
       
   845         LIBXML_ELEMENT->ns = NULL; // NULL means "NO NAMESPACE"(I.E. "UNDEFINED NAMESPACE")
       
   846         }
       
   847     }
       
   848 
       
   849 // ---------------------------------------------------------------------------------------------
       
   850 // Finds namespace declaration that has specific prefix in the scope for given node
       
   851 //
       
   852 // Prefix "" or NULL are considered the same, meaning "<b>NO PREFIX</b>".
       
   853 // If namespace declaration for "no prefix" is searched, then default namespace is returned. 
       
   854 //
       
   855 // @return Namespace handler, which may be NULL if prefix is not bound.
       
   856 //
       
   857 // NULL result for "no prefix" means that default namespace is undefined.
       
   858 // ---------------------------------------------------------------------------------------------
       
   859 //
       
   860 EXPORT_C TXmlEngNamespace TXmlEngElement::LookupNamespaceByPrefixL(
       
   861     const TDesC8& aPrefix ) const
       
   862     {
       
   863     // OOM may happen ONLY during a lookup for {"xml","http://www.w3.org/XML/1998/namespace"}
       
   864 
       
   865     xmlChar* pref = xmlCharFromDesC8L(aPrefix);
       
   866     // Allow "" instead of NULL
       
   867     if(pref && !*pref)
       
   868         {
       
   869         delete pref;
       
   870         pref = NULL;
       
   871         }
       
   872         
       
   873     xmlNsPtr ns = xmlSearchNs(
       
   874                         LIBXML_ELEMENT->doc,
       
   875                         LIBXML_ELEMENT,
       
   876                         pref
       
   877                 );
       
   878     delete pref;
       
   879     // Default namespace undeclarations are never returned  
       
   880     if (ns && ns->href && !*ns->href)
       
   881         ns = NULL;
       
   882     return TXmlEngNamespace(ns);
       
   883     }
       
   884 
       
   885 // ---------------------------------------------------------------------------------------------
       
   886 // Finds namespace declaration that has specific namespace URI
       
   887 // in the scope for the given node.
       
   888 //
       
   889 // @param aUri  Namespace URI, for which namespace declaration is searched
       
   890 // @return Handler to the namespace declaration that binds given namespace URI to some prefix 
       
   891 //         or NULL if the binding is not active at the scope of this element.
       
   892 //
       
   893 // NULL value of aUri is equivalent to "" and means "<b>UNDEFINED NAMESPACE</b>". 
       
   894 // For such URI  a NULL namespace handle is always returned even if there is
       
   895 // namespace undeclaration, which has "" URI (and NULL prefix).
       
   896 //
       
   897 // <b>Hint:</b><p>
       
   898 // Use returned instance of TXmlEngNamespace as aNsDef argument to element's methods
       
   899 // that create new element's child elements and attributes. The same handler
       
   900 // may be used on more deep descentants of the reference element (and doing
       
   901 // this way will generally increase performance of DOM tree construction).<br />
       
   902 // <span class="color:red;">However</span>, if namespace bindings are not controlled
       
   903 // for element's children and prefix, which is bound to the search namespace, is
       
   904 // rebound to some other namespace URI, then reusing namespace may lead to
       
   905 // unwanted result.
       
   906 //
       
   907 // Consider an example:
       
   908 // @code
       
   909 //     TXmlEngElement root = doc.DocumentElement();
       
   910 //     TXmlEngNamespace targetNs = root.AddNamespaceDeclarationL("http://example.com/","ex");
       
   911 //     TXmlEngElement el_1 = root.AddNewElementL("outer", targetNs);
       
   912 //     TXmlEngElement el_2 = el_1.AddNewElementL("inner"); // element without prefix
       
   913 //
       
   914 //     // NOTE: prefix "ex" is not bound to "http://example.com/" anymore
       
   915 //     el_2.AddNamespaceDeclarationL("http://whatever.com/","ex");
       
   916 //     TXmlEngElement el_3 = el_2.AddNewElementL("problem", targetNs);
       
   917 //     ...
       
   918 // @endcode
       
   919 //
       
   920 // The sought result was (showing expanded names of elements):
       
   921 // @code
       
   922 //     --> "root"
       
   923 //         --> {"http://example.com/","outer"}
       
   924 //         --> "inner"
       
   925 //             -->{"http://example.com/","problem"}
       
   926 //                 ...
       
   927 //             <--
       
   928 //         <-- "inner"
       
   929 //         <-- {"http://example.com/","outer"}
       
   930 //         ...
       
   931 //     <-- </root>
       
   932 // @endcode
       
   933 // and it may look that it has been achieved. Indeed, if namespace of element "problem"
       
   934 // was queried, it would have URI "http://example.com/" and prefix "ex".
       
   935 // However, if namespace URI was looked up by "problem"'s prefix, it would be
       
   936 // "http://whatever.com/". We have created illegal DOM tree.
       
   937 //
       
   938 // The actual DOM tree in serialized form will be:
       
   939 // @code
       
   940 //     <root>
       
   941 //         <ex:outer xmlns:ex="http://example.com/">
       
   942 //            <inner xmlns:ex="http://example.com/">
       
   943 //                 <ex:problem>
       
   944 //                 ...
       
   945 //                 </ex:problem>
       
   946 //            </inner>
       
   947 //         </ex:outer>
       
   948 //        ...
       
   949 //     </root>
       
   950 // @endcode
       
   951 //
       
   952 // So, reuse of namespace handlers should be performed with special care.
       
   953 //
       
   954 // @note
       
   955 //     At the moment it is possible to retrieve namespace declaration nodes
       
   956 //     whose prefixes were rebound. Be careful when use returned TXmlEngNamespace object
       
   957 //     for creation of new elements. In later releases, this method will perform
       
   958 //     safe lookup. And so far, it is better to make check that prefix of returned
       
   959 //     namespace declaration has not rebound:
       
   960 // @code
       
   961 //     TXmlEngNamespace ns = element.LookupNamespaceByUri("a_uri");
       
   962 //     if (element.LookupNamespaceByPrefix(ns.Prefix()).IsSameNode(ns)){
       
   963 //         ... // now it is safe to create new elements by using "ns"
       
   964 //         element.AddNewElementL("product",ns);
       
   965 //         ...
       
   966 //     }
       
   967 // @endcode
       
   968 // ---------------------------------------------------------------------------------------------
       
   969 //
       
   970 EXPORT_C TXmlEngNamespace TXmlEngElement::LookupNamespaceByUriL(
       
   971     const TDesC8& aUri ) const
       
   972     {
       
   973     // OOM may happen ONLY during a lookup for {"xml","http://www.w3.org/XML/1998/namespace"}
       
   974 
       
   975     xmlChar* uri = xmlCharFromDesC8L(aUri);
       
   976 
       
   977 	if(!uri || !*uri)
       
   978 		{
       
   979 		delete uri;
       
   980 		return NULL;
       
   981 		}
       
   982 	else
       
   983 		{
       
   984         TXmlEngNamespace ns = xmlSearchNsByHref(
       
   985                             LIBXML_ELEMENT->doc,
       
   986                             LIBXML_ELEMENT,
       
   987                             uri);	
       
   988         delete uri;	
       
   989 		if(LookupNamespaceByPrefixL(ns.Prefix()).IsSameNode(ns))
       
   990 			{
       
   991 			return ns;
       
   992 			}
       
   993 		else
       
   994 			{
       
   995 			return NULL; //the binding is not active at the scope of this element
       
   996 			}
       
   997 		}
       
   998     }
       
   999 
       
  1000 // ---------------------------------------------------------------------------------------------
       
  1001 // Retrieves implicitly declared on every XML infoset binding
       
  1002 // of 'xml' prefix to XML's namespace URI:
       
  1003 // "http://www.w3.org/XML/1998/namespace"
       
  1004 //
       
  1005 // @return Handler to {xml,"http://www.w3.org/XML/1998/namespace"} prefix
       
  1006 //            binding in the current document
       
  1007 //
       
  1008 // The result should be used for creating attributes beloging to the XML namespace
       
  1009 // (xml:lang, xml:space, xml:id , etc.)
       
  1010 //
       
  1011 // DO NOT USE methods LookupNamespaceByUri(TDesC8) and LookupNamespaceByPrefix(TDesC8)
       
  1012 // (with "http://www.w3.org/XML/1998/namespace" and "xml" arguments) for retrieving
       
  1013 // namespace node, since in a case of [possible] memory allocation fault
       
  1014 // NULL result is returned (and breaks your program silently)
       
  1015 //
       
  1016 // @note   Normally 'xml' prefix is bound to XML namespace URI in the document
       
  1017 //         node, BUT if current node is not a part of the document tree yet,
       
  1018 //         the requested namespace declaration WILL BE ADDED to the current node.
       
  1019 //         This is the reason why the method may fail in OOM conditions.
       
  1020 // ---------------------------------------------------------------------------------------------
       
  1021 //
       
  1022 EXPORT_C TXmlEngNamespace TXmlEngElement::TheXMLNamespaceL() const
       
  1023     {
       
  1024     xmlNsPtr ns = xmlSearchNs(
       
  1025                         LIBXML_ELEMENT->doc,
       
  1026                         LIBXML_ELEMENT,
       
  1027                         BAD_CAST "xml");
       
  1028     OOM_IF_NULL(ns);
       
  1029     return ns;
       
  1030     }
       
  1031 
       
  1032 // ---------------------------------------------------------------------------------------------
       
  1033 // Performs search of namespace handler in the scope of the element. This method will
       
  1034 // create new namespace declaration on the element if such namespace is not available.
       
  1035 //
       
  1036 // @param aNsUri   Searched namespace
       
  1037 // @param aPrefix  Prefix to use for <b>new</b> namespace declaration (if it is to be created)
       
  1038 //
       
  1039 // @return    TXmlEngNamespace handler that may be used to create new attributes and child elements of
       
  1040 //             the element. The namespace may be one of those existed previously or was created
       
  1041 //
       
  1042 // @see LookupNamespacebyUriL
       
  1043 // @note
       
  1044 //     Be sure not to use the result of this method for non-descendants of the element or in situations
       
  1045 //     when prefix overlapping might occur (read also about general considerations of attributes
       
  1046 //     and elements creation using namespace handlers)
       
  1047 // ---------------------------------------------------------------------------------------------
       
  1048 //
       
  1049 EXPORT_C TXmlEngNamespace TXmlEngElement::FindOrCreateNsDeclL(
       
  1050     const TDesC8& aNsUri,
       
  1051     const TDesC8& aPrefix )
       
  1052     {
       
  1053     TXmlEngNamespace ns = LookupNamespaceByUriL(aNsUri);
       
  1054     if (aNsUri.Length() && ns.IsNull())
       
  1055         {
       
  1056         // Some (not the undefined one) namespace was not declared yet 
       
  1057         ns = AddNamespaceDeclarationL(aNsUri, aPrefix);
       
  1058         }
       
  1059     else
       
  1060         {
       
  1061         // There is a namespacedeclaration,
       
  1062         // check that it is not "shielded" (its prefix is not rebound)
       
  1063         if (! LookupNamespaceByPrefixL(ns.Prefix()).IsSameNode(ns))
       
  1064             {
       
  1065             // it was rebound, so we rebound it again
       
  1066             ns = AddNamespaceDeclarationL(aNsUri, aPrefix);
       
  1067             }
       
  1068         }
       
  1069     return ns;
       
  1070 }
       
  1071 
       
  1072 // ---------------------------------------------------------------------------------------------
       
  1073 // Performs search on the element and its ascendants for any namespace declaration
       
  1074 // with given URI and create a new namespace declaration with some (unique) prefix
       
  1075 // if the search was not successful.
       
  1076 // ---------------------------------------------------------------------------------------------
       
  1077 //
       
  1078 EXPORT_C TXmlEngNamespace TXmlEngElement::FindOrCreateNsDeclL(
       
  1079     const TDesC8& aNsUri )
       
  1080     {
       
  1081     _LIT8(KAutoPrefix,"_pr%d");
       
  1082     const TInt KMaxPrefLength = 20;
       
  1083     TBuf8<KMaxPrefLength> prefix;
       
  1084     
       
  1085     TXmlEngNamespace ns = LookupNamespaceByUriL(aNsUri);
       
  1086     if (ns.NotNull())
       
  1087         return ns;
       
  1088 
       
  1089     TBool ready = false;
       
  1090     TUint ind = 0;
       
  1091     
       
  1092     while(!ready)
       
  1093         {
       
  1094         // generate prefix
       
  1095         ++ind;
       
  1096         prefix.Format(KAutoPrefix,ind);
       
  1097                 
       
  1098         // check
       
  1099         ns = LookupNamespaceByPrefixL(prefix);
       
  1100         ready = ns.IsNull();
       
  1101         }
       
  1102     return AddNamespaceDeclarationL(aNsUri, prefix);
       
  1103     }
       
  1104 
       
  1105 // ---------------------------------------------------------------------------------------------
       
  1106 // Adds namespace declaration to the current element, a binding of prefix to namespace URI.
       
  1107 //
       
  1108 // If same namespace declaration exists (same prefix and URI), redundant namespace declaration
       
  1109 // will not be created.
       
  1110 //
       
  1111 // Both NULL or "" (empty string) may be used for "UNDEFINED URI" and "NO PREFIX" values of arguments. 
       
  1112 //
       
  1113 // @return  A handle to the created (or found, if there is such) namespace declaration node.
       
  1114 //          If namespace undeclaration is being created, NULL handle is returned -- it can be
       
  1115 //          used in node-creation methods that take namespace handle as an argument.
       
  1116 //
       
  1117 // @note   Undeclaring of default namespace (xmlns="") is supported by
       
  1118 //         SetNoDefaultNamespace() method
       
  1119 //
       
  1120 // @see SetNoDefaulNamespace()
       
  1121 //
       
  1122 // @note   By adding namespace declaration that rebinds prefix mapping (or default namespace)
       
  1123 //         used by nodes lower in the tree, document tree may become
       
  1124 //         wrongly constructed, because references to namespace declaration are
       
  1125 //         not updated. However, after serialization the document will have
       
  1126 //         desired structure.
       
  1127 //         Use this method with care!
       
  1128 // ---------------------------------------------------------------------------------------------
       
  1129 //
       
  1130 EXPORT_C TXmlEngNamespace TXmlEngElement::AddNamespaceDeclarationL(
       
  1131     const TDesC8& aNsUri,
       
  1132     const TDesC8& aPrefix )
       
  1133     {
       
  1134     if ( !LIBXML_ELEMENT )
       
  1135     	{
       
  1136     	User::Leave(KXmlEngErrNullNode);
       
  1137     	}
       
  1138     if(!aNsUri.Length() && aPrefix.Length())
       
  1139         {
       
  1140         User::Leave(KXmlEngErrWrongUseOfAPI);
       
  1141         }
       
  1142         
       
  1143     // Now we allow NULL instead of ""
       
  1144     xmlChar* nsUri = NULL;
       
  1145     if(aNsUri.Length())
       
  1146         {
       
  1147         nsUri = xmlCharFromDesC8L(aNsUri);
       
  1148         }
       
  1149     else
       
  1150         {
       
  1151         nsUri = (xmlChar*)new(ELeave) TUint8[1];
       
  1152         *(Mem::Copy((TAny*)nsUri, aNsUri.Ptr(), aNsUri.Length())) = 0;
       
  1153         }
       
  1154         
       
  1155     CleanupStack::PushL(nsUri);
       
  1156     
       
  1157     // Now we allow "" instead of NULL
       
  1158     xmlChar* pref = NULL;
       
  1159     if(aPrefix.Length())
       
  1160         {
       
  1161         pref = xmlCharFromDesC8L(aPrefix);
       
  1162         }
       
  1163     
       
  1164     xmlNsPtr ns = xmlNewNs(
       
  1165                     LIBXML_ELEMENT,
       
  1166                     nsUri,
       
  1167                     pref);
       
  1168     
       
  1169     delete pref;                
       
  1170     CleanupStack::PopAndDestroy(nsUri);
       
  1171     
       
  1172     TEST_OOM_FLAG;
       
  1173     if (!ns)
       
  1174         {
       
  1175         // OOM or Already exists
       
  1176         if (HasNsDeclarationForPrefixL(aPrefix))
       
  1177             {
       
  1178             return FindOrCreateNsDeclL(aNsUri); // unique prefix will be generated
       
  1179             }
       
  1180         }
       
  1181     return TXmlEngNamespace(ns);
       
  1182     }
       
  1183 
       
  1184 // ---------------------------------------------------------------------------------------------
       
  1185 // Checks whether a prefix has been bound in this element (not in one of its ascendants)
       
  1186 //
       
  1187 // Use this method for preventig prefix-name collision in a element node
       
  1188 //
       
  1189 // @return TRUE if there is already namespace declaration that uses aPrefix on this element
       
  1190 // ---------------------------------------------------------------------------------------------
       
  1191 //
       
  1192 EXPORT_C TBool TXmlEngElement::HasNsDeclarationForPrefixL(
       
  1193     const TDesC8& aPrefix ) const
       
  1194     {
       
  1195     xmlChar* prefix;
       
  1196     if(!aPrefix.Length())
       
  1197         {
       
  1198         prefix = NULL;
       
  1199         }
       
  1200     else
       
  1201         {
       
  1202         prefix = xmlCharFromDesC8L(aPrefix);
       
  1203         }
       
  1204     // Convert "" into NULL
       
  1205     TXmlEngConstString pref((char*) prefix);
       
  1206     xmlNsPtr ns = LIBXML_ELEMENT->nsDef;
       
  1207     while (ns)
       
  1208         if(pref.Equals((char*)ns->prefix))
       
  1209             {
       
  1210             delete prefix;
       
  1211             return true;
       
  1212             }            
       
  1213         else
       
  1214             ns = ns->next;
       
  1215     delete prefix;
       
  1216     return false;
       
  1217     }
       
  1218 
       
  1219 // ---------------------------------------------------------------------------------------------
       
  1220 // Copies the element with its attributes, but not child nodes
       
  1221 //
       
  1222 // If context is preserved, then all namespace declarations that are in the element are
       
  1223 // writen to element's start tag too.
       
  1224 // ---------------------------------------------------------------------------------------------
       
  1225 //
       
  1226 EXPORT_C TXmlEngElement TXmlEngElement::ElementCopyNoChildrenL(
       
  1227     TBool aPreserveNsContext ) const
       
  1228     {
       
  1229     if ( !LIBXML_ELEMENT )
       
  1230     	{
       
  1231     	User::Leave(KXmlEngErrNullNode);
       
  1232     	}
       
  1233     //
       
  1234     xmlNodePtr ncopy = xmlStaticCopyNode(LIBXML_ELEMENT, NULL, NULL, 0 /* shallow copy */);
       
  1235     if (!ncopy) // for a copy of element node, it's not neccessary to check OOM flag
       
  1236         {
       
  1237         OOM_HAPPENED;
       
  1238         }
       
  1239     // OOM will be checked in the very end of methods
       
  1240     if (LIBXML_ELEMENT->properties)
       
  1241         {
       
  1242         ncopy->properties = xmlCopyPropList(ncopy, LIBXML_ELEMENT->properties);
       
  1243         }
       
  1244     if (aPreserveNsContext)
       
  1245         {
       
  1246         if (LIBXML_ELEMENT->nsDef)
       
  1247             {
       
  1248             ncopy->nsDef = xmlCopyNamespaceList(LIBXML_ELEMENT->nsDef);
       
  1249             }
       
  1250         }
       
  1251     // DONE: OOM: check OOM flag
       
  1252     if (xmlOOMFlag())
       
  1253         {
       
  1254         xmlFreeNode(ncopy);
       
  1255         OOM_HAPPENED;
       
  1256         }
       
  1257     TXmlEngElement el(ncopy);
       
  1258     OwnerDocument().TakeOwnership(el);
       
  1259     return el;
       
  1260     }
       
  1261 
       
  1262 // ---------------------------------------------------------------------------------------------
       
  1263 // Resets element's content: all child nodes are removed
       
  1264 // ---------------------------------------------------------------------------------------------
       
  1265 //
       
  1266 EXPORT_C void TXmlEngElement::RemoveChildren()
       
  1267     {
       
  1268     //
       
  1269     if(!LIBXML_ELEMENT)
       
  1270         {
       
  1271         return;
       
  1272         }
       
  1273     xmlFreeNodeList(LIBXML_ELEMENT->children);
       
  1274     LIBXML_ELEMENT->children = NULL;
       
  1275     LIBXML_ELEMENT->last = NULL;
       
  1276     }
       
  1277 
       
  1278 // ---------------------------------------------------------------------------------------------
       
  1279 // Resets element's attributes
       
  1280 // ---------------------------------------------------------------------------------------------
       
  1281 //
       
  1282 EXPORT_C void TXmlEngElement::RemoveAttributes()
       
  1283     {
       
  1284     if(!LIBXML_ELEMENT)
       
  1285         {
       
  1286         return;
       
  1287         }
       
  1288     //
       
  1289     xmlFreePropList(LIBXML_ELEMENT->properties);
       
  1290     LIBXML_ELEMENT->properties = NULL;
       
  1291     }
       
  1292 
       
  1293 // ---------------------------------------------------------------------------------------------
       
  1294 // Resets all namespace declarations made in the element
       
  1295 //
       
  1296 // @note There can be references to these namespace declaration from elsewhere!
       
  1297 //       Use ReconcileNamespacesL() to fix that.
       
  1298 // ---------------------------------------------------------------------------------------------
       
  1299 //
       
  1300 EXPORT_C void TXmlEngElement::RemoveNamespaceDeclarations()
       
  1301     {
       
  1302     if (!LIBXML_ELEMENT)
       
  1303         {
       
  1304         return;
       
  1305         }
       
  1306     xmlNsPtr ns = LIBXML_ELEMENT->nsDef;
       
  1307     while(ns)
       
  1308         {
       
  1309         ResetNs(LIBXML_NODE,ns);
       
  1310         ns = ns->next;
       
  1311         }
       
  1312     
       
  1313     xmlFreeNsList(LIBXML_ELEMENT->nsDef);
       
  1314     LIBXML_ELEMENT->nsDef = NULL;
       
  1315     }
       
  1316 
       
  1317 // ---------------------------------------------------------------------------------------------
       
  1318 // Copies attributes from another element
       
  1319 //
       
  1320 // It may be a very convenient method for initializing element with a set of predefined attributes.
       
  1321 //
       
  1322 // @note
       
  1323 //     Namespaces of the this element may need to be reconciled if copied attributes
       
  1324 //     belong to any namespace that is not declared on some ascendant of this node.
       
  1325 //
       
  1326 // @see ReconcileNamespacesL()
       
  1327 // ---------------------------------------------------------------------------------------------
       
  1328 //
       
  1329 EXPORT_C void TXmlEngElement::CopyAttributesL(
       
  1330     TXmlEngElement aSrc )
       
  1331     {
       
  1332     if ( !LIBXML_ELEMENT )
       
  1333     	{
       
  1334     	User::Leave(KXmlEngErrNullNode);
       
  1335     	}
       
  1336     //
       
  1337     if (INTERNAL_NODEPTR(aSrc)->properties)
       
  1338         {
       
  1339         xmlAttrPtr plist = xmlCopyPropList(LIBXML_ELEMENT, INTERNAL_NODEPTR(aSrc)->properties);
       
  1340         OOM_IF_NULL(plist);
       
  1341 
       
  1342         if (LIBXML_ELEMENT->properties)
       
  1343             {
       
  1344             xmlAttrPtr last = LIBXML_ELEMENT->properties;
       
  1345             while (last->next)
       
  1346                 {
       
  1347                 last = last->next;
       
  1348                 }
       
  1349             last->next = plist;
       
  1350             }
       
  1351         else
       
  1352             {
       
  1353             LIBXML_ELEMENT->properties = plist;
       
  1354             }
       
  1355         }
       
  1356     }
       
  1357 
       
  1358 // ---------------------------------------------------------------------------------------------
       
  1359 // Copies a list of elements.
       
  1360 //
       
  1361 // Elements are appended to the element's children list.
       
  1362 //
       
  1363 // @note Namespaces of the this element may need to be reconciled after copy operation
       
  1364 // @see  ReconcileNamespacesL()
       
  1365 // ---------------------------------------------------------------------------------------------
       
  1366 //
       
  1367 EXPORT_C void TXmlEngElement::CopyChildrenL(
       
  1368     TXmlEngElement aSrc )
       
  1369     {
       
  1370     if ( !LIBXML_ELEMENT )
       
  1371     	{
       
  1372     	User::Leave(KXmlEngErrNullNode);
       
  1373     	}
       
  1374     if ( aSrc.IsNull() )
       
  1375     	{
       
  1376     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
  1377     	}
       
  1378     if (INTERNAL_NODEPTR(aSrc)->children)
       
  1379         {
       
  1380         xmlNodePtr plist = xmlStaticCopyNodeList(
       
  1381                                 INTERNAL_NODEPTR(aSrc)->children,
       
  1382                                 LIBXML_ELEMENT->doc,
       
  1383                                 LIBXML_ELEMENT);
       
  1384         OOM_IF_NULL(plist);
       
  1385         xmlNodePtr last = plist;
       
  1386         while (last->next)
       
  1387             {
       
  1388             last = last->next;
       
  1389             }
       
  1390         if (LIBXML_ELEMENT->children)
       
  1391             {
       
  1392             LIBXML_ELEMENT->last->next = plist;
       
  1393             plist->prev = LIBXML_ELEMENT->last;
       
  1394             }
       
  1395         else
       
  1396             {
       
  1397             LIBXML_ELEMENT->children = plist;
       
  1398             }
       
  1399         LIBXML_ELEMENT->last = last;
       
  1400         }
       
  1401     }
       
  1402 
       
  1403 // ---------------------------------------------------------------------------------------------
       
  1404 // Removes attribute with given name and namespace URI(if such exists).
       
  1405 // Memory allocated for the attribute is freed.
       
  1406 // ---------------------------------------------------------------------------------------------
       
  1407 //
       
  1408 EXPORT_C void TXmlEngElement::RemoveChildElementsL(
       
  1409     const TDesC8& aLocalName,
       
  1410     const TDesC8& aNamespaceUri )
       
  1411     {
       
  1412     if (!LIBXML_ELEMENT)
       
  1413         {
       
  1414         return;
       
  1415         }
       
  1416     //pjj18
       
  1417     RXmlEngNodeList<TXmlEngElement> eList;
       
  1418     
       
  1419     eList.OpenL(
       
  1420             LIBXML_ELEMENT->children,
       
  1421             TXmlEngNode::EElement,
       
  1422             aLocalName,
       
  1423             aNamespaceUri);
       
  1424 
       
  1425     TXmlEngElement el;
       
  1426     while ((el = eList.Next()).NotNull())
       
  1427         el.Remove();
       
  1428     eList.Close();
       
  1429     }
       
  1430 
       
  1431 // ---------------------------------------------------------------------------------------------
       
  1432 // Renames the element.
       
  1433 // ---------------------------------------------------------------------------------------------
       
  1434 //
       
  1435 EXPORT_C void TXmlEngElement::RenameElementL(
       
  1436 	const TDesC8& aLocalName, 
       
  1437 	const TDesC8& aNamespaceUri, 
       
  1438 	const TDesC8& aPrefix)
       
  1439 	{
       
  1440 
       
  1441         xmlNodePtr element = INTERNAL_NODEPTR(*this);
       
  1442 
       
  1443     	XE_ASSERT_DEBUG( element->type == XML_ELEMENT_NODE );
       
  1444 
       
  1445        	const xmlChar* oldName = element->name;
       
  1446        	
       
  1447        	XE_ASSERT_ALWAYS(aLocalName.Length());
       
  1448        	
       
  1449        	element->name = xmlCharFromDesC8L(aLocalName);
       
  1450        	
       
  1451        	xmlFree((void*)oldName );
       
  1452        	
       
  1453         if (aNamespaceUri.Length() || aPrefix.Length())
       
  1454             {
       
  1455             TXmlEngNamespace ns = (*this).FindOrCreateNsDeclL(aNamespaceUri, aPrefix);
       
  1456             element->ns = INTERNAL_NSPTR(ns);
       
  1457             }
       
  1458          
       
  1459 	}
       
  1460 
       
  1461 // ========================================================================================
       
  1462 
       
  1463 // DOM Level 3 Core
       
  1464 
       
  1465 
       
  1466 // ---------------------------------------------------------------------------------------------
       
  1467 // Links attribute into tree
       
  1468 //
       
  1469 // The replaced attribute node is not returned and just deleted
       
  1470 // ---------------------------------------------------------------------------------------------
       
  1471 //
       
  1472 EXPORT_C void TXmlEngElement::SetAttributeNodeL(
       
  1473     TXmlEngAttr aNewAttr )
       
  1474     {
       
  1475     AppendChildL(aNewAttr);
       
  1476     xmlReconciliateNs(LIBXML_ELEMENT->doc, LIBXML_NODE);
       
  1477     }
       
  1478 
       
  1479 // ---------------------------------------------------------------------------------------------
       
  1480 // Returns value of attribute with given name and namespace URI
       
  1481 //  
       
  1482 // @param aLocalName       - local name of attribute node
       
  1483 // @param aNamespaceUri    - namespace URI of attribute
       
  1484 // ---------------------------------------------------------------------------------------------
       
  1485 //   
       
  1486 EXPORT_C TPtrC8 TXmlEngElement::AttributeValueL(
       
  1487     const TDesC8& aLocalName,
       
  1488     const TDesC8& aNamespaceUri ) const
       
  1489     {
       
  1490     TXmlEngAttr attr = AttributeNodeL(aLocalName, aNamespaceUri);
       
  1491     if( attr.IsNull() )
       
  1492     	return KNullDesC8();
       
  1493     else
       
  1494     	return attr.Value();
       
  1495     }
       
  1496 
       
  1497 // ---------------------------------------------------------------------------------------------
       
  1498 // Sets value of attribute; attribute is created if there is no such attribute yet
       
  1499 //
       
  1500 // @note
       
  1501 //     If prefix is not NULL (or ""), then namespace URI may not be empty
       
  1502 //     see http://www.w3.org/TR/REC-xml-names/#ns-decl (Definition #3)
       
  1503 // ---------------------------------------------------------------------------------------------
       
  1504 //
       
  1505 EXPORT_C void TXmlEngElement::SetAttributeL(
       
  1506     const TDesC8& aLocalName,
       
  1507     const TDesC8& aValue,
       
  1508     const TDesC8& aNamespaceUri,
       
  1509     const TDesC8& aPrefix )
       
  1510     {
       
  1511     if ( aLocalName.Length() <= 0 )
       
  1512     	{
       
  1513     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
  1514     	}
       
  1515 
       
  1516     TXmlEngAttr attr = AttributeNodeL(aLocalName, aNamespaceUri);
       
  1517     if (attr.NotNull())
       
  1518         {
       
  1519         attr.SetValueL(aValue);
       
  1520         }
       
  1521     else
       
  1522         {
       
  1523         AddNewAttributeL(aLocalName, aValue, aNamespaceUri, aPrefix);
       
  1524         }
       
  1525     }
       
  1526 
       
  1527 // ---------------------------------------------------------------------------------------------
       
  1528 // Removes attribute with given name and namespace URI(if such exists).
       
  1529 // Memory allocated for the attribute is freed.
       
  1530 // ---------------------------------------------------------------------------------------------
       
  1531 //
       
  1532 EXPORT_C void TXmlEngElement::RemoveAttributeL(
       
  1533     const TDesC8& aLocalName,
       
  1534     const TDesC8& aNamespaceUri )
       
  1535     {
       
  1536     TXmlEngAttr attr = AttributeNodeL(aLocalName, aNamespaceUri);
       
  1537     xmlRemoveProp(INTERNAL_ATTRPTR(attr));
       
  1538     }
       
  1539 
       
  1540 // ---------------------------------------------------------------------------------------------
       
  1541 // Retrieves attribute node from specific namespace by its name.
       
  1542 // 
       
  1543 // @return Attribute node with matching namespace URI and name
       
  1544 // @note Use "" (empty string) for namespace name, not NULL (for <i>undefined namespace</i>)
       
  1545 // ---------------------------------------------------------------------------------------------
       
  1546 //
       
  1547 EXPORT_C TXmlEngAttr TXmlEngElement::AttributeNodeL(
       
  1548     const TDesC8& aLocalName,
       
  1549     const TDesC8& aNamespaceUri ) const
       
  1550     {
       
  1551     //pjj18
       
  1552     RXmlEngNodeList<TXmlEngAttr> attList;
       
  1553         
       
  1554     attList.OpenL(
       
  1555             LIBXML_ELEMENT->properties,
       
  1556             TXmlEngNode::EAttribute,
       
  1557             aLocalName,
       
  1558             aNamespaceUri);
       
  1559     TXmlEngAttr attr = attList.Next();
       
  1560     attList.Close();
       
  1561     return attr;
       
  1562     }
       
  1563 
       
  1564 // ---------------------------------------------------------------------------------------------
       
  1565 // Initializes list of child elements with matching name and namespace URI.
       
  1566 //
       
  1567 // @note This method does not lists all descedants of the element, only child elements
       
  1568 // ---------------------------------------------------------------------------------------------
       
  1569 //
       
  1570 EXPORT_C void TXmlEngElement::GetElementsByTagNameL(
       
  1571     RXmlEngNodeList<TXmlEngElement>& aList,
       
  1572     const TDesC8& aLocalName,
       
  1573     const TDesC8& aNamespaceUri ) const
       
  1574     {
       
  1575     aList.OpenL(
       
  1576         LIBXML_ELEMENT->children,
       
  1577         TXmlEngNode::EElement,
       
  1578         aLocalName,
       
  1579         aNamespaceUri);
       
  1580     }
       
  1581