webservices/wsxml/src/senxmlelement.cpp
changeset 0 62f9d29f7211
child 29 5743aa3a72c3
equal deleted inserted replaced
-1:000000000000 0:62f9d29f7211
       
     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 "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:      
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 
       
    25 // INCLUDE FILES
       
    26 #include "SenXmlElement.h"
       
    27 #include "SenXmlConstants.h" // KSenColon, ++
       
    28 #include "SenXmlUtils.h"
       
    29 
       
    30 #include "senxmldebug.h"
       
    31 
       
    32 #ifdef SYMBIAN_SECURE_ECOM 
       
    33     // for 2.8, 3.0 or newer:
       
    34     #include <xml/attribute.h> // needed for RAttributeArray
       
    35 #else // for 2.6 or older
       
    36     #include "Attribute.h"
       
    37 #endif
       
    38 
       
    39 using namespace Xml;
       
    40 
       
    41 namespace
       
    42     {
       
    43 
       
    44 //    _LIT8(KColon,            ":");
       
    45 //    _LIT8(KLessThan,         "<");
       
    46 //    _LIT8(KGreaterThan,      ">");
       
    47 //    _LIT8(KSpace,            " ");
       
    48 //    _LIT8(KDblQuot,          "\"");
       
    49 //    _LIT8(KEqualsDblQuot,    "=\"");
       
    50 //    _LIT8(KSlashGreaterThan, "/>");
       
    51 //    _LIT8(KSenLessThanSlash,    "</");
       
    52 //    _LIT8(KSpaceXmlns,       " xmlns");
       
    53 //    _LIT8(KXmlns,            "xmlns");
       
    54 //    _LIT8(KXmlNsAttNamePlusColon, "xmlns:"); 
       
    55     const TInt KFlatBufSize        = 64;
       
    56     }
       
    57 
       
    58 
       
    59 EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aLocalName)
       
    60     {
       
    61     CSenXmlElement* pNew = new (ELeave) CSenXmlElement;
       
    62     CleanupStack::PushL(pNew);
       
    63     pNew->BaseConstructL(aLocalName);
       
    64     CleanupStack::Pop(); // pNew;
       
    65     return pNew;
       
    66     }
       
    67 
       
    68 EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri,
       
    69                                                 const TDesC8& aLocalName)
       
    70     {
       
    71     CSenXmlElement* pNew = new (ELeave) CSenXmlElement;
       
    72     CleanupStack::PushL(pNew);
       
    73     pNew->BaseConstructL(aNsUri, aLocalName);
       
    74     CleanupStack::Pop(); // pNew;
       
    75     return pNew;
       
    76     }
       
    77 
       
    78 EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri,
       
    79                                                 const TDesC8& aLocalName,
       
    80                                                 const TDesC8& aQName)
       
    81     {
       
    82     CSenXmlElement* pNew = new (ELeave) CSenXmlElement;
       
    83     CleanupStack::PushL(pNew);
       
    84     pNew->BaseConstructL(aNsUri, aLocalName, aQName);
       
    85     CleanupStack::Pop(); // pNew;
       
    86     return pNew;
       
    87     }
       
    88 
       
    89 EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri,
       
    90                                                 const TDesC8& aLocalName,
       
    91                                                 const TDesC8& aQName,
       
    92                                                 const RAttributeArray& apAttrs)
       
    93     {
       
    94     CSenXmlElement* pNew = new (ELeave) CSenXmlElement;
       
    95     CleanupStack::PushL(pNew);
       
    96     pNew->BaseConstructL(aNsUri, aLocalName, aQName, apAttrs);
       
    97     CleanupStack::Pop(); // pNew;
       
    98     return pNew;
       
    99     }
       
   100 
       
   101 
       
   102 EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri,
       
   103                                                 const TDesC8& aLocalName,
       
   104                                                 const TDesC8& aQName,
       
   105                                                 const RAttributeArray& apAttrs,
       
   106                                                 CSenElement& aParent)
       
   107     {
       
   108     CSenXmlElement* pNew = new (ELeave) CSenXmlElement;
       
   109     CleanupStack::PushL(pNew);
       
   110     pNew->BaseConstructL(aNsUri, aLocalName, aQName, apAttrs, aParent);
       
   111     CleanupStack::Pop(); // pNew;
       
   112     return pNew;
       
   113     }
       
   114 
       
   115 EXPORT_C CSenXmlElement::CSenXmlElement()
       
   116 : ipLocalName(NULL),
       
   117   ipContentBuf(NULL),
       
   118   ipParent(NULL),
       
   119   ipNamespace(NULL)
       
   120     {
       
   121     }
       
   122 
       
   123 EXPORT_C CSenXmlElement::~CSenXmlElement()
       
   124     {
       
   125     if(ipContentWriteStream)
       
   126         {
       
   127         ipContentWriteStream->Close();
       
   128         delete ipContentWriteStream;
       
   129         ipContentWriteStream = NULL;
       
   130         }
       
   131 
       
   132     if(ipAttrs)
       
   133         {
       
   134         ipAttrs->ResetAndDestroy();
       
   135         delete ipAttrs;
       
   136         ipAttrs = NULL; // not required
       
   137         }
       
   138     if(ipElements)
       
   139         {
       
   140         ipElements->ResetAndDestroy();
       
   141         delete ipElements;
       
   142         ipElements = NULL; // not required
       
   143         }
       
   144     if(ipNamespaces)
       
   145         {
       
   146         ipNamespaces->ResetAndDestroy();
       
   147         delete ipNamespaces;
       
   148         ipNamespaces = NULL; // not required
       
   149         }
       
   150 
       
   151     delete ipLocalName;
       
   152     ipLocalName = NULL; // not required
       
   153 
       
   154 
       
   155     delete ipContentBuf;
       
   156     ipContentBuf = NULL; // not required
       
   157 
       
   158     }
       
   159 
       
   160 
       
   161 
       
   162 EXPORT_C void CSenXmlElement::BaseConstructL(const TDesC8& aLocalName)
       
   163     {
       
   164     SenXmlUtils::LeaveOnInvalidElementNameL(aLocalName);
       
   165     ipLocalName = aLocalName.AllocL();
       
   166     }
       
   167 
       
   168 EXPORT_C void CSenXmlElement::BaseConstructL(const TDesC8& aNsUri,
       
   169                                               const TDesC8& aLocalName)
       
   170     {
       
   171     SenXmlUtils::LeaveOnInvalidElementNameL(aLocalName);
       
   172     if(aNsUri.Length()>0)
       
   173         {
       
   174         SetNamespaceL(aNsUri);
       
   175         }
       
   176     ipLocalName = aLocalName.AllocL();
       
   177     }
       
   178 
       
   179 EXPORT_C void CSenXmlElement::BaseConstructL(   const TDesC8& aNsUri,
       
   180                                                 const TDesC8& aLocalName,
       
   181                                                 const TDesC8& aQName)
       
   182     {
       
   183     SenXmlUtils::LeaveOnInvalidElementNameL(aLocalName);
       
   184     SenXmlUtils::LeaveOnInvalidElementNameL(aQName);
       
   185     ipLocalName = aLocalName.AllocL();
       
   186     TPtrC8 ptrPrefix(KNullDesC8);
       
   187 
       
   188     if (aQName.Length() > 0 )
       
   189         {
       
   190         TInt colon = aQName.Locate(':');
       
   191         if (colon > 0) // Note: 0 also treated as no prefix
       
   192             {
       
   193             ptrPrefix.Set(aQName.Ptr(),colon);
       
   194             }
       
   195         }
       
   196 
       
   197     SetNamespaceL(ptrPrefix, aNsUri);
       
   198     }
       
   199 
       
   200 EXPORT_C void CSenXmlElement::BaseConstructL(   const TDesC8& aNsUri,
       
   201                                                 const TDesC8& aLocalName,
       
   202                                                 const TDesC8& aQName,
       
   203                                                 const RAttributeArray& apAttrs)
       
   204     {
       
   205     BaseConstructL(aNsUri, aLocalName, aQName);
       
   206     SetAttributesL(apAttrs);
       
   207     }
       
   208 
       
   209 EXPORT_C void CSenXmlElement::BaseConstructL(   const TDesC8& aNsUri,
       
   210                                                 const TDesC8& aLocalName,
       
   211                                                 const TDesC8& aQName,
       
   212                                                 const RAttributeArray& apAttrs,
       
   213                                                 CSenElement& aParent    )
       
   214     {
       
   215     // parent must be set here at first line, because
       
   216     // namespace setting dependends of it(!)
       
   217     ipParent = &aParent;
       
   218 
       
   219     BaseConstructL(aNsUri, aLocalName, aQName);
       
   220     SetAttributesL(apAttrs);
       
   221     }
       
   222 
       
   223 EXPORT_C void CSenXmlElement::SetAttributesL(const RAttributeArray& apAttrs)
       
   224     {
       
   225     AddAttributesL(apAttrs);
       
   226     }
       
   227 
       
   228 
       
   229 EXPORT_C void CSenXmlElement::AddAttributesL(const RAttributeArray& apAttrs)
       
   230     {
       
   231     TInt count(apAttrs.Count());
       
   232     HBufC8* qName = NULL;
       
   233     for(TInt i=0; i<count; i++)
       
   234         {
       
   235         const TPtrC8 localname = apAttrs[i].Attribute().LocalName().DesC();
       
   236         const TPtrC8 prefix = apAttrs[i].Attribute().Prefix().DesC();
       
   237         const TPtrC8 value = apAttrs[i].Value().DesC();
       
   238 
       
   239         SenXmlUtils::BuildQNameL(prefix, localname, qName);
       
   240 
       
   241         CleanupStack::PushL(qName);
       
   242 
       
   243         HBufC8* encodedValue = NULL;
       
   244         TBool encoded = 
       
   245             SenXmlUtils::EncodeHttpCharactersL(value, encodedValue);
       
   246 
       
   247         if (encoded)
       
   248             {
       
   249             CleanupStack::PushL(encodedValue);
       
   250             AddAttributeL(*qName, localname, *encodedValue); 
       
   251             // note: this intentionally
       
   252             // skips the 2 param 
       
   253             // AddAttributeL() function
       
   254 
       
   255             CleanupStack::PopAndDestroy(); // encodedValue
       
   256             }
       
   257         else
       
   258             {
       
   259             AddAttributeL(*qName, localname, value); 
       
   260             // note: this intentionally
       
   261             // skips the 2 param 
       
   262             // AddAttributeL() function
       
   263             }
       
   264 
       
   265         CleanupStack::PopAndDestroy(); // qName
       
   266         }
       
   267     }
       
   268 
       
   269 EXPORT_C const TDesC8& CSenXmlElement::AddAttributeL(const TDesC8& aQName,
       
   270                                                      const TDesC8& aLocalName,
       
   271                                                      const TDesC8& aValue)
       
   272     {
       
   273     const TDesC8& nsPrefix = NsPrefix();
       
   274     // first we check for possible namespace declarations...
       
   275     if ( aQName == KSenXmlns || aLocalName == KSenXmlns)
       
   276         {
       
   277             if(nsPrefix.Length() > 0)
       
   278                 {
       
   279                 // we have an additional namespace declaration
       
   280                 AddNamespaceL(KNullDesC8(), aValue);
       
   281                 }
       
   282             else
       
   283                 {
       
   284                 // this is a default name space declaration
       
   285                 SetNamespaceL(aValue);                
       
   286                 }
       
   287                 
       
   288         }
       
   289     else if (aLocalName == NsPrefix())
       
   290         {
       
   291         //we have a new declaration for the namespace of this element
       
   292         SetNamespaceL(aLocalName, aValue);
       
   293         }
       
   294     else if(aQName.Find(KSenXmlNsAttNamePlusColon) == 0)
       
   295         {
       
   296         // we have an additional namespace declaration
       
   297         AddNamespaceL(aLocalName, aValue);
       
   298         }
       
   299     else
       
   300         {
       
   301         // we have a real attribute!
       
   302         CSenBaseAttribute* pAttribute = CSenBaseAttribute::NewL(aQName,
       
   303                                                                 aLocalName,
       
   304                                                                 aValue);
       
   305         AddAttributeL(pAttribute);
       
   306         }
       
   307     return aValue;
       
   308     }
       
   309 
       
   310 
       
   311 
       
   312 EXPORT_C const TDesC8& CSenXmlElement::AddAttributeL(const TDesC8& aAttrName,
       
   313                                                       const TDesC8& aValue)
       
   314     {
       
   315     // note, the aAttrName may be a qualified name or simply localname
       
   316     // strip off the possible prefix from possible qualified name:
       
   317     TPtrC8 localName = SenXmlUtils::LocalName(aAttrName);
       
   318     return AddAttributeL(aAttrName, localName, aValue);
       
   319     }
       
   320 
       
   321 // takes the ownership of aAttribute
       
   322 EXPORT_C const TDesC8& CSenXmlElement::AddAttributeL(
       
   323                                                 CSenBaseAttribute* apAttribute)
       
   324     {
       
   325     CSenBaseAttribute* pOldAtt = FindAttr(apAttribute->Name());
       
   326 
       
   327     // if attribute array is not yet allocated, instantiate here
       
   328     if(!ipAttrs)
       
   329         {
       
   330         ipAttrs = new (ELeave) RPointerArray<CSenBaseAttribute>;
       
   331         }
       
   332 
       
   333     if(!pOldAtt)
       
   334         {
       
   335         // transfrer the ownership to this class:
       
   336         ipAttrs->Append(apAttribute);
       
   337         return apAttribute->Value();
       
   338         }
       
   339     else
       
   340         {
       
   341         pOldAtt->SetValueL(apAttribute->Value());
       
   342         delete apAttribute;
       
   343         apAttribute = NULL;
       
   344         return pOldAtt->Value();
       
   345         }
       
   346     }
       
   347 
       
   348 
       
   349 EXPORT_C CSenBaseAttribute* CSenXmlElement::FindAttr(const TDesC8& aName)
       
   350     {
       
   351     if(ipAttrs)
       
   352         {
       
   353         TInt count(ipAttrs->Count());
       
   354         for (TInt i = 0; i < count; i++)
       
   355             {
       
   356             CSenBaseAttribute* pAttribute = (*ipAttrs)[i];
       
   357             if(pAttribute->Name() == aName)
       
   358                 {
       
   359                 return pAttribute;
       
   360                 }
       
   361             }
       
   362         }
       
   363     return NULL;
       
   364     }
       
   365 
       
   366 
       
   367 EXPORT_C TInt CSenXmlElement::IndexOfElement(const TDesC8& aNsUri,
       
   368                                               const TDesC8& aLocalName) const
       
   369     {
       
   370     if(ipElements)
       
   371         {
       
   372         TInt count(ipElements->Count());
       
   373 
       
   374         for (TInt i = 0; i < count; i++)
       
   375             {
       
   376             CSenElement* pElement = (*ipElements)[i];
       
   377             const TDesC8& nsUri = pElement->NamespaceURI();
       
   378             const TDesC8& localName = pElement->LocalName();
       
   379             if ((nsUri == aNsUri) && (localName == aLocalName))
       
   380                 {
       
   381                 return i;
       
   382                 }
       
   383             }
       
   384         }
       
   385     return KErrNotFound;
       
   386     }
       
   387 
       
   388 EXPORT_C const TDesC8& CSenXmlElement::LocalName() const
       
   389     {
       
   390     if (ipLocalName == NULL)
       
   391         {
       
   392         return KNullDesC8();
       
   393         }
       
   394     else
       
   395         {
       
   396         return *ipLocalName;
       
   397         }
       
   398     }
       
   399 
       
   400 EXPORT_C const TDesC8& CSenXmlElement::NamespaceURI() const
       
   401     {
       
   402     if (ipNamespace)
       
   403         {
       
   404         return ipNamespace->URI();
       
   405         }
       
   406     else
       
   407         {
       
   408         return KNullDesC8();
       
   409         }
       
   410     }
       
   411 
       
   412 EXPORT_C const TDesC8& CSenXmlElement::NsPrefix() const
       
   413     {
       
   414     if (!ipNamespace)
       
   415         {
       
   416         return KNullDesC8();
       
   417         }
       
   418     else
       
   419         {
       
   420         return ipNamespace->Prefix();
       
   421         }
       
   422     }
       
   423 
       
   424 EXPORT_C TBool CSenXmlElement::HasContent() const
       
   425     {
       
   426     if (!ipContentBuf)
       
   427         {
       
   428         return EFalse;
       
   429         }
       
   430     else
       
   431         {
       
   432         return (ipContentBuf->Size() > 0);
       
   433         }
       
   434     }
       
   435 
       
   436 EXPORT_C TPtrC8 CSenXmlElement::Content() const
       
   437     {
       
   438     if (!ipContentBuf)
       
   439         {
       
   440         return KNullDesC8();
       
   441         }
       
   442     else
       
   443         {
       
   444         TPtrC8 p8 = ipContentBuf->Ptr(0);
       
   445         return p8;
       
   446         }
       
   447     }
       
   448 
       
   449 
       
   450 EXPORT_C HBufC* CSenXmlElement::ContentUnicodeL() const
       
   451     {
       
   452     HBufC* pRet = SenXmlUtils::ToUnicodeLC(Content());
       
   453     CleanupStack::Pop(); // pRet;
       
   454     return pRet;
       
   455     }
       
   456 
       
   457 EXPORT_C TPtrC8 CSenXmlElement::SetContentL(const TDesC8& aContent)
       
   458     {
       
   459     AllocContentBufL(); 
       
   460 	if(ipContentBuf)
       
   461 		{
       
   462 		ipContentBuf->ResizeL(aContent.Size());
       
   463 		ipContentBuf->Write(0,
       
   464         TPtrC8(REINTERPRET_CAST(const TUint8*, aContent.Ptr()),
       
   465                                                 aContent.Size())
       
   466         );
       
   467 		if(ipContentWriteStream)
       
   468 			{
       
   469 			// Reset stream
       
   470 			ipContentWriteStream->Open(*ipContentBuf);
       
   471 			}
       
   472 		}
       
   473     return Content();
       
   474     }
       
   475 
       
   476 EXPORT_C RWriteStream& CSenXmlElement::ContentWriteStreamL()
       
   477     {
       
   478     AllocContentBufL();
       
   479     // Allocate stream
       
   480     if(!ipContentWriteStream)
       
   481         {
       
   482         ipContentWriteStream = new (ELeave) RBufWriteStream;
       
   483         }
       
   484     ipContentWriteStream->Open(*ipContentBuf);
       
   485     return *ipContentWriteStream;
       
   486     }
       
   487 
       
   488 // NOTE: assumes(!) that the namespace is same(!)
       
   489 // Optimization 
       
   490 // RPointerArray<CSenElement>* or NULL if no elements have been added!
       
   491 EXPORT_C RPointerArray<CSenElement>& CSenXmlElement::ElementsL()
       
   492     {
       
   493     if(!ipElements)
       
   494         {
       
   495         ipElements = new (ELeave) RPointerArray<CSenElement>;
       
   496         }
       
   497     return *ipElements;
       
   498     }
       
   499 
       
   500 EXPORT_C TInt CSenXmlElement::ElementsL(
       
   501                                     RPointerArray<CSenElement>& aElementArray,
       
   502                                     const TDesC8& aNsUri,
       
   503                                     const TDesC8& aLocalName)
       
   504     {
       
   505     TInt retVal(KErrNotFound);
       
   506 
       
   507     if(ipElements) // return KErrNotFound, if zero elements have been added
       
   508         {
       
   509         TInt count(ipElements->Count());
       
   510 
       
   511         if (count > 0) // return KErrNotFound, if owned array is empty
       
   512             {
       
   513             CSenElement* pElement = NULL;
       
   514             for (TInt i=0; i<count; i++)
       
   515                 {
       
   516                 pElement = (*ipElements)[i];
       
   517                 if ( (aLocalName == pElement->LocalName()) &&
       
   518                      (aNsUri == pElement->NamespaceURI()) )
       
   519                     {
       
   520                     aElementArray.Append(pElement);
       
   521                     }
       
   522                 }
       
   523             retVal = KErrNone;
       
   524             }
       
   525         }
       
   526     return retVal;
       
   527     }
       
   528 
       
   529 EXPORT_C TInt CSenXmlElement::ElementsL(
       
   530                                     RPointerArray<CSenElement>& aElementArray,
       
   531                                     const TDesC8& aLocalName)
       
   532     {
       
   533     return ElementsL(aElementArray,NamespaceURI(),aLocalName);
       
   534     }
       
   535 
       
   536 EXPORT_C const TDesC8* CSenXmlElement::AttrValue(const TDesC8& aName)
       
   537     {
       
   538     CSenBaseAttribute* pAttr = FindAttr(aName);
       
   539     if (pAttr == NULL)
       
   540         {
       
   541         return NULL;
       
   542         }
       
   543     else
       
   544         {
       
   545         return &(pAttr->Value());
       
   546         }
       
   547     }
       
   548 
       
   549 EXPORT_C void CSenXmlElement::AddAttrL(const TDesC8& aName,
       
   550                                         const TDesC8& aValue)
       
   551     {
       
   552     CSenBaseAttribute* pAttr = FindAttr(aName);
       
   553     if (!pAttr)
       
   554         {
       
   555         if(!ipAttrs)
       
   556             {
       
   557             ipAttrs = new (ELeave) RPointerArray<CSenBaseAttribute>;
       
   558             }
       
   559 
       
   560         User::LeaveIfError(ipAttrs->Append(CSenBaseAttribute::NewL(aName,
       
   561                                                                  aValue)));
       
   562         }
       
   563     else
       
   564         {
       
   565         pAttr->SetValueL(aValue);
       
   566         }
       
   567     }
       
   568 
       
   569 EXPORT_C CSenElement* CSenXmlElement::Parent()
       
   570     {
       
   571     return ipParent;
       
   572     }
       
   573 
       
   574 EXPORT_C CSenElement* CSenXmlElement::SetParent(CSenElement* apParent)  // IOP
       
   575     {
       
   576     if (apParent && ipParent != apParent)
       
   577         {
       
   578         ipParent = apParent;
       
   579         if (!ipNamespace)
       
   580             {
       
   581             // check if there is a default namespace declared in the scope of
       
   582             // the parent
       
   583             const CSenNamespace* pParentNamespace =
       
   584                 ((CSenXmlElement*) ipParent)->Namespace(KNullDesC8,ETrue);
       
   585             if (pParentNamespace && pParentNamespace->Prefix() == KNullDesC8)
       
   586                 {
       
   587                 ipNamespace = (CSenNamespace*)pParentNamespace;
       
   588                 }
       
   589             }
       
   590         else
       
   591             {
       
   592             //check if the parent already has a namespace for this element
       
   593             // if so remove it from the local namespace table
       
   594             const CSenNamespace* pNs = ipParent->Namespace(KNullDesC8,
       
   595                                                     ipNamespace->URI());
       
   596             if (pNs && pNs != ipNamespace)
       
   597                 {
       
   598                 if (ipNamespace->Compare(*pNs) ||
       
   599                     ipNamespace->Prefix().Length() == 0)
       
   600                     {
       
   601                     //prefix is also identical or this element has no prefix
       
   602                     if(ipNamespaces)
       
   603                         {
       
   604                         TInt nsIndex = ipNamespaces->Find(ipNamespace);
       
   605                         if ( nsIndex != KErrNotFound)
       
   606                             {
       
   607                             ipNamespaces->Remove(nsIndex);
       
   608                             }
       
   609                         }
       
   610                     delete ipNamespace;
       
   611                     ipNamespace = NULL;
       
   612                     ipNamespace = (CSenNamespace*)pNs;
       
   613                     }
       
   614                 }
       
   615 
       
   616             }
       
   617         }
       
   618     return apParent;
       
   619     }
       
   620 
       
   621 EXPORT_C MSenElement& CSenXmlElement::Root()
       
   622     {
       
   623     if (ipParent == NULL)
       
   624         {
       
   625         return *this;
       
   626         }
       
   627     else
       
   628         {
       
   629         return ipParent->Root();
       
   630         }
       
   631     }
       
   632 
       
   633 EXPORT_C CSenElement* CSenXmlElement::Element(const TDesC8& aLocalName)
       
   634     {
       
   635     return Element(NamespaceURI(), aLocalName);
       
   636     }
       
   637 
       
   638 EXPORT_C CSenElement* CSenXmlElement::Element(const TDesC8& aNsUri,
       
   639                                                const TDesC8& aLocalName)
       
   640     {
       
   641     if(ipElements)
       
   642         {
       
   643         TInt idx = IndexOfElement(aNsUri, aLocalName);
       
   644         if (idx < 0)
       
   645             {
       
   646             return NULL;
       
   647             }
       
   648         else
       
   649             {
       
   650             return (*ipElements)[idx];
       
   651             }
       
   652         }
       
   653     return NULL;
       
   654     }
       
   655 
       
   656 EXPORT_C CSenElement* CSenXmlElement::CreateElementL(const TDesC8& aNsPrefix,
       
   657                                                       const TDesC8& aLocalName)
       
   658     {
       
   659     CSenElement* pNewElement = NULL;
       
   660 
       
   661     if (aNsPrefix.Length() > 0)
       
   662         {
       
   663         CSenNamespace* pNamespace = (CSenNamespace*)Namespace(aNsPrefix);
       
   664         if (pNamespace)
       
   665             {
       
   666             HBufC8 *pQName =
       
   667                 HBufC8::NewLC(aNsPrefix.Length() + aLocalName.Length() +5);
       
   668             TPtr8 ptr = pQName->Des();
       
   669             ptr.Append(aNsPrefix);
       
   670             ptr.Append(':');
       
   671             ptr.Append(aLocalName);
       
   672             pNewElement =
       
   673                 CSenXmlElement::NewL(pNamespace->URI(), aLocalName, *pQName);
       
   674             CleanupStack::PopAndDestroy(); // pQName
       
   675             }
       
   676         }
       
   677     else
       
   678         {
       
   679         pNewElement = CSenXmlElement::NewL(aLocalName);
       
   680         }
       
   681 
       
   682     return pNewElement; // Returns NULL if required namespace can not be found!
       
   683     }
       
   684 
       
   685 EXPORT_C CSenElement& CSenXmlElement::InsertElementL(
       
   686                                           CSenElement& aElement,
       
   687                                           const CSenElement& aBeforeElement)
       
   688     {
       
   689     TInt index(KErrNotFound);
       
   690 
       
   691     // allocate element array, if not already reserved
       
   692     if(!ipElements)
       
   693         {
       
   694         ipElements = new (ELeave) RPointerArray<CSenElement>;
       
   695         }
       
   696     else
       
   697         {
       
   698         // search only if array is not brand new
       
   699         index = ipElements->Find(&aBeforeElement);
       
   700         }
       
   701 
       
   702     if (index != KErrNotFound)
       
   703         {
       
   704         // repleace element
       
   705         User::LeaveIfError(ipElements->Insert(&aElement,index));
       
   706         }
       
   707     else
       
   708         {
       
   709         // add new element
       
   710         User::LeaveIfError(ipElements->Append(&aElement));
       
   711         }
       
   712     aElement.SetParent(this);
       
   713     return aElement;
       
   714     }
       
   715 
       
   716 EXPORT_C CSenElement& CSenXmlElement::AddElementL(CSenElement& aElement)
       
   717     {
       
   718     // allocate element array, if not already reserved
       
   719     if(!ipElements)
       
   720         {
       
   721         ipElements = new (ELeave) RPointerArray<CSenElement>;
       
   722         }
       
   723 
       
   724     User::LeaveIfError(ipElements->Append(&aElement));
       
   725     aElement.SetParent(this);
       
   726     return aElement;
       
   727     }
       
   728 
       
   729 EXPORT_C CSenElement& CSenXmlElement::AddElementL(const TDesC8& aNsUri,
       
   730                                                    const TDesC8& aLocalName)
       
   731     {
       
   732     return AddElementL(*CSenXmlElement::NewL(aNsUri, aLocalName));
       
   733     }
       
   734 
       
   735 EXPORT_C CSenElement& CSenXmlElement::AddElementL(
       
   736     const TDesC8& aNsUri,
       
   737     const TDesC8& aLocalName,
       
   738     const TDesC8& aQName
       
   739     )
       
   740     {
       
   741     return AddElementL(*CSenXmlElement::NewL(aNsUri, aLocalName, aQName));
       
   742     }
       
   743 
       
   744 EXPORT_C CSenElement& CSenXmlElement::AddElementL(const TDesC8& aLocalName)
       
   745     {
       
   746     return AddElementL(*CSenXmlElement::NewL(aLocalName));
       
   747     }
       
   748 
       
   749 EXPORT_C CSenElement* CSenXmlElement::RemoveElement(CSenElement& aElement)
       
   750     {
       
   751     CSenElement* pElement = NULL;
       
   752 
       
   753     if(ipElements)
       
   754         {
       
   755         TInt idx = ipElements->Find(&aElement);
       
   756         if (idx >= 0)
       
   757             {
       
   758             pElement = (*ipElements)[idx];
       
   759             ipElements->Remove(idx);
       
   760             pElement->SetParent(NULL);
       
   761             return pElement;
       
   762             }
       
   763         }
       
   764     return pElement;
       
   765     }
       
   766 
       
   767 EXPORT_C CSenElement* CSenXmlElement::RemoveElement(const TDesC8& aNsUri,
       
   768                                                      const TDesC8& aLocalName)
       
   769     {
       
   770     TInt idx = IndexOfElement(aNsUri, aLocalName);
       
   771     if (idx >= 0)
       
   772         {
       
   773         CSenElement* pElement = (*ipElements)[idx];
       
   774         ipElements->Remove(idx);
       
   775         pElement->SetParent(NULL);
       
   776         return pElement;
       
   777         }
       
   778     else
       
   779         {
       
   780         return NULL;
       
   781         }
       
   782     }
       
   783 
       
   784 EXPORT_C CSenElement* CSenXmlElement::RemoveElement(const TDesC8& aLocalName)
       
   785     {
       
   786     return RemoveElement(NamespaceURI(), aLocalName);
       
   787     }
       
   788 
       
   789 EXPORT_C CSenElement* CSenXmlElement::ReplaceElementL(CSenElement& aElement)
       
   790     {
       
   791     CSenElement* pOldElement =
       
   792                 RemoveElement(aElement.NamespaceURI(), aElement.LocalName());
       
   793     CleanupStack::PushL(pOldElement);
       
   794     AddElementL(aElement);
       
   795     CleanupStack::Pop(); // pOldElement;
       
   796     return pOldElement;
       
   797     }
       
   798 
       
   799 EXPORT_C HBufC8* CSenXmlElement::AsXmlL()
       
   800     {
       
   801     CBufFlat *pBuf = CBufFlat::NewL(KFlatBufSize);
       
   802     CleanupStack::PushL(pBuf);
       
   803     TPtrC8 p = WriteToBufL(*pBuf);
       
   804     HBufC8* pRet = p.AllocL();
       
   805     CleanupStack::PopAndDestroy(); // pBuf;
       
   806     return pRet;
       
   807 
       
   808     }
       
   809 
       
   810 EXPORT_C HBufC* CSenXmlElement::AsXmlUnicodeL()
       
   811     {
       
   812     CBufFlat *pBuf = CBufFlat::NewL(KFlatBufSize);
       
   813     CleanupStack::PushL(pBuf);
       
   814     TPtrC8 p8 = WriteToBufL(*pBuf);
       
   815     HBufC* pRet = SenXmlUtils::ToUnicodeLC(p8);
       
   816     CleanupStack::Pop(); // pop pRet;
       
   817     CleanupStack::PopAndDestroy(); // pBuf;
       
   818     return pRet;
       
   819     }
       
   820 
       
   821 EXPORT_C TPtrC8 CSenXmlElement::WriteToBufL(CBufBase& aBuf)
       
   822     {
       
   823     RBufWriteStream bufWs(aBuf);
       
   824     CleanupClosePushL(bufWs);
       
   825     this->WriteAsXMLToL(bufWs);
       
   826     CleanupStack::PopAndDestroy(); // bufWs.Close();
       
   827     return aBuf.Ptr(0);
       
   828     }
       
   829 
       
   830 EXPORT_C void CSenXmlElement::WriteAsXMLToL(RWriteStream& aWriteStream)
       
   831     {
       
   832     // Find out whether we should declare the namespace
       
   833     TPtrC8 nsPrefix = NsPrefix();
       
   834 
       
   835     // Element name
       
   836     aWriteStream.WriteL(KSenLessThan);
       
   837     if (nsPrefix.Length() > 0)
       
   838         {
       
   839         aWriteStream.WriteL(nsPrefix);
       
   840         aWriteStream.WriteL(KSenColon);
       
   841         }
       
   842     aWriteStream.WriteL(*ipLocalName);
       
   843 
       
   844     
       
   845     if ((ipAttrs && ipAttrs->Count() > 0) || 
       
   846          (ipNamespaces && ipNamespaces->Count() > 0))
       
   847         {
       
   848         WriteNamespacesToL(aWriteStream);
       
   849         WriteAttrsToL(aWriteStream);
       
   850         }
       
   851 
       
   852     // Elements and content
       
   853     if ((ipElements && ipElements->Count() > 0) || HasContent())
       
   854         {
       
   855         aWriteStream.WriteL(KSenGreaterThan);
       
   856 
       
   857         // Body
       
   858         WriteElementsToL(aWriteStream);
       
   859         WriteContentToL(aWriteStream);
       
   860 
       
   861         // Closing element
       
   862         aWriteStream.WriteL(KSenLessThanSlash);
       
   863         if (nsPrefix.Length() > 0)
       
   864             {
       
   865             aWriteStream.WriteL(nsPrefix);
       
   866             aWriteStream.WriteL(KSenColon);
       
   867             }
       
   868         aWriteStream.WriteL(*ipLocalName);
       
   869         aWriteStream.WriteL(KSenGreaterThan);
       
   870         }
       
   871     else
       
   872         {
       
   873         aWriteStream.WriteL(KSenSlashGreaterThan);
       
   874         }
       
   875     }
       
   876 
       
   877 EXPORT_C void CSenXmlElement::WriteAttrToL(RWriteStream& aWriteStream,
       
   878                                             const TDesC8& aName,
       
   879                                             const TDesC8& aValue)
       
   880     {
       
   881     aWriteStream.WriteL(KSenSpace);
       
   882     aWriteStream.WriteL(aName);
       
   883     aWriteStream.WriteL(KSenEqualsDblQuot);
       
   884     aWriteStream.WriteL(aValue);
       
   885     aWriteStream.WriteL(KSenDblQuot);
       
   886     }
       
   887 
       
   888 EXPORT_C void CSenXmlElement::WriteAttrsToL(RWriteStream& aWriteStream)
       
   889     {
       
   890     if(ipAttrs)
       
   891         {
       
   892         TInt count(ipAttrs->Count());
       
   893         for (TInt i = 0; i < count; i++)
       
   894             {
       
   895             WriteAttrToL(aWriteStream, (*ipAttrs)[i]->Name(), (*ipAttrs)[i]->Value());
       
   896             }
       
   897         }
       
   898     }
       
   899 
       
   900 EXPORT_C void CSenXmlElement::WriteNamespacesToL(RWriteStream& aWriteStream)
       
   901     {
       
   902     if(ipNamespaces)
       
   903         {
       
   904         CSenNamespace* ns = NULL;
       
   905         TInt count = ipNamespaces->Count();
       
   906         for (TInt i=0; i < count; i++)
       
   907             {
       
   908             ns = (*ipNamespaces)[i];
       
   909             if (ns)
       
   910                 {
       
   911                 aWriteStream.WriteL(KSenSpaceXmlns);
       
   912                 if (ns->Prefix().Length() > 0)
       
   913                     {
       
   914                     aWriteStream.WriteL(KSenColon);
       
   915                     aWriteStream.WriteL(ns->Prefix());
       
   916                     }
       
   917                 aWriteStream.WriteL(KSenEqualsDblQuot);
       
   918                 aWriteStream.WriteL(ns->URI());
       
   919                 aWriteStream.WriteL(KSenDblQuot);
       
   920                 }
       
   921             }
       
   922         }
       
   923     }
       
   924 
       
   925 EXPORT_C void CSenXmlElement::WriteElementsToL(RWriteStream& aWriteStream)
       
   926     {
       
   927     if(ipElements)
       
   928         {
       
   929         TInt elementCount(ipElements->Count());
       
   930         for (TInt i=0; i<elementCount; i++)
       
   931             {
       
   932             (*ipElements)[i]->WriteAsXMLToL(aWriteStream);
       
   933             }
       
   934         }
       
   935     }
       
   936 
       
   937 EXPORT_C void CSenXmlElement::WriteContentToL(RWriteStream& aWriteStream)
       
   938     {
       
   939     aWriteStream.WriteL(Content());
       
   940     }
       
   941 
       
   942 EXPORT_C MSenElement* CSenXmlElement::AsElement()
       
   943     {
       
   944     return this;
       
   945     }
       
   946 
       
   947 EXPORT_C void CSenXmlElement::AllocContentBufL()
       
   948     {
       
   949     if(!ipContentBuf)
       
   950         {
       
   951         ipContentBuf = CBufFlat::NewL(KFlatBufSize);
       
   952         }
       
   953     }
       
   954 
       
   955 EXPORT_C void CSenXmlElement::SetNamespaceL(const TDesC8& aNsUri)
       
   956     {
       
   957     SetNamespaceL(KNullDesC8, aNsUri);
       
   958     }
       
   959 
       
   960 EXPORT_C void CSenXmlElement::SetNamespaceL(const TDesC8& aNsPrefix,
       
   961                                             const TDesC8& aNsUri)
       
   962     {
       
   963     if (aNsUri.Length() > 0)
       
   964         {
       
   965         ipNamespace = (CSenNamespace*) Namespace(aNsPrefix, aNsUri);
       
   966         if (!ipNamespace) // not already defined
       
   967             {
       
   968             // allocate array if not already reserved
       
   969             if(!ipNamespaces)
       
   970                 {
       
   971                 ipNamespaces = new (ELeave) RPointerArray<CSenNamespace>;
       
   972                 }
       
   973             ipNamespace = CSenNamespace::NewL(aNsPrefix, aNsUri);
       
   974             ipNamespaces->Append(ipNamespace);
       
   975             }
       
   976         }
       
   977     }
       
   978 
       
   979 EXPORT_C const CSenNamespace* CSenXmlElement::Namespace()
       
   980     {
       
   981     return ipNamespace;
       
   982     }
       
   983 
       
   984 EXPORT_C const CSenNamespace* CSenXmlElement::Namespace(
       
   985                                                     const TDesC8& aNsPrefix)
       
   986     {
       
   987     return Namespace(aNsPrefix,ETrue);
       
   988     }
       
   989 
       
   990 EXPORT_C const CSenNamespace* CSenXmlElement::Namespace(
       
   991                                                     const TDesC8& aNsPrefix,
       
   992                                                     const TBool aCheckInParent)
       
   993     {
       
   994     if (aNsPrefix.Length() == 0) return NULL;
       
   995 
       
   996     const CSenNamespace* pNamespace = NULL;
       
   997 
       
   998     if(ipNamespaces)
       
   999         {
       
  1000         TInt count(ipNamespaces->Count());
       
  1001         for (TInt i=0; i<count && pNamespace == NULL; i++)
       
  1002             {
       
  1003             pNamespace = (*ipNamespaces)[i];
       
  1004             if (pNamespace)
       
  1005                 {
       
  1006                 if (pNamespace->Prefix() != aNsPrefix) pNamespace = NULL;
       
  1007                 }
       
  1008             }
       
  1009         }
       
  1010 
       
  1011     if (pNamespace == NULL && ipParent && aCheckInParent)
       
  1012         {
       
  1013         pNamespace = ipParent->Namespace(aNsPrefix);
       
  1014         }
       
  1015 
       
  1016     return pNamespace;
       
  1017     }
       
  1018 
       
  1019 
       
  1020 EXPORT_C const CSenNamespace* CSenXmlElement::Namespace(
       
  1021                                                     const TDesC8& aNsPrefix,
       
  1022                                                     const TDesC8& aUri)
       
  1023     {
       
  1024     // If prefix == NULL, then any prefix is ok
       
  1025     const CSenNamespace* pNs = NULL;
       
  1026     // Check if the namespace has already been declared
       
  1027     
       
  1028     if(ipNamespaces)
       
  1029         {
       
  1030         TInt count = ipNamespaces->Count();
       
  1031         if (count != 0)
       
  1032             {
       
  1033             for (TInt i=0; i<count; i++)
       
  1034                 {
       
  1035                 pNs = (*ipNamespaces)[i];
       
  1036                 if (!pNs->Compare(aNsPrefix, aUri))
       
  1037                     {
       
  1038                     pNs = NULL; // not equal
       
  1039                     }
       
  1040                 else
       
  1041                     {
       
  1042                     break;
       
  1043                     }
       
  1044                 }
       
  1045             }
       
  1046         }
       
  1047     if (pNs == NULL && ipParent != NULL)
       
  1048         {
       
  1049         // if no namespace defined, but there is a parent, ask its namespace
       
  1050         pNs = ipParent->Namespace(aNsPrefix, aUri);
       
  1051         }
       
  1052     return pNs;
       
  1053     }
       
  1054 
       
  1055 EXPORT_C RPointerArray<CSenBaseAttribute>& CSenXmlElement::AttributesL()
       
  1056     {
       
  1057     // if attribute array is not yet allocated, instantiate here
       
  1058     if(!ipAttrs)
       
  1059         {
       
  1060         ipAttrs = new (ELeave) RPointerArray<CSenBaseAttribute>;
       
  1061         }
       
  1062     return *ipAttrs;
       
  1063     }
       
  1064 
       
  1065 EXPORT_C RPointerArray<CSenNamespace>& CSenXmlElement::NamespacesL()
       
  1066     {
       
  1067     if(!ipNamespaces)
       
  1068         {
       
  1069         ipNamespaces = new (ELeave) RPointerArray<CSenNamespace>;
       
  1070         }
       
  1071     return *ipNamespaces;
       
  1072     }
       
  1073 
       
  1074 EXPORT_C void CSenXmlElement::CopyFromL(CSenElement& aSource)
       
  1075     {
       
  1076     TPtrC8 sourceContent = aSource.Content();
       
  1077     if (sourceContent.Length() > 0)
       
  1078         {
       
  1079         if (ipContentBuf == NULL)
       
  1080             {
       
  1081             SetContentL(sourceContent);
       
  1082             }
       
  1083         else
       
  1084             {
       
  1085             RBufWriteStream bufWs(*ipContentBuf);
       
  1086             CleanupClosePushL(bufWs);
       
  1087             bufWs.WriteL(sourceContent);
       
  1088             CleanupStack::PopAndDestroy(); // close bufWs
       
  1089             }
       
  1090         }
       
  1091 
       
  1092     RPointerArray<CSenNamespace> sourceNamespaces = aSource.NamespacesL();
       
  1093     if (sourceNamespaces.Count() > 0)
       
  1094         {
       
  1095         for (TInt i=0;i<sourceNamespaces.Count(); i++)
       
  1096             {
       
  1097             CSenNamespace* pNamespace = sourceNamespaces[i];
       
  1098             CSenNamespace* pNewNamespace =
       
  1099                 CSenNamespace::NewL(pNamespace->Prefix(),pNamespace->URI());
       
  1100             CleanupStack::PushL(pNewNamespace);
       
  1101 
       
  1102             // allocate array if not already reserved
       
  1103             if(!ipNamespaces)
       
  1104                 {
       
  1105                 ipNamespaces = new (ELeave) RPointerArray<CSenNamespace>;
       
  1106                 }
       
  1107             
       
  1108 #ifdef EKA2
       
  1109             ipNamespaces->AppendL(pNewNamespace);
       
  1110 #else
       
  1111             User::LeaveIfError(ipNamespaces->Append(pNewNamespace));
       
  1112 #endif
       
  1113             CleanupStack::Pop(pNewNamespace);
       
  1114             }
       
  1115         }
       
  1116     SetNamespaceL(aSource.NsPrefix(), aSource.NamespaceURI());
       
  1117 
       
  1118     RPointerArray<CSenBaseAttribute> sourceAttributes = aSource.AttributesL();
       
  1119     if (sourceAttributes.Count() > 0)
       
  1120         {
       
  1121         for (TInt i=0;i<sourceAttributes.Count(); i++)
       
  1122             {
       
  1123             CSenBaseAttribute* pBaseAttribute = sourceAttributes[i];
       
  1124 
       
  1125             // 2005-04-28: check for duplicate and override existing value if
       
  1126             // attribute already exists.
       
  1127             CSenBaseAttribute* pOriginal = FindAttr(pBaseAttribute->Name());
       
  1128             if (pOriginal)
       
  1129                 {
       
  1130                 pOriginal->SetValueL(pBaseAttribute->Value());
       
  1131                 continue;
       
  1132                 }
       
  1133 
       
  1134             CSenBaseAttribute* pNewBaseAttribute =
       
  1135                 CSenBaseAttribute::NewL(pBaseAttribute->Name(),
       
  1136                                         pBaseAttribute->Value());
       
  1137             CleanupStack::PushL(pNewBaseAttribute);
       
  1138 
       
  1139             // if attribute array is not yet allocated, instantiate here
       
  1140             if(!ipAttrs)
       
  1141                 {
       
  1142                 ipAttrs = new (ELeave) RPointerArray<CSenBaseAttribute>;
       
  1143                 }
       
  1144 
       
  1145 #ifdef EKA2
       
  1146             ipAttrs->AppendL(pNewBaseAttribute);
       
  1147 #else
       
  1148             User::LeaveIfError(ipAttrs->Append(pNewBaseAttribute));
       
  1149 #endif
       
  1150             CleanupStack::Pop(pNewBaseAttribute);
       
  1151             }
       
  1152         }
       
  1153 
       
  1154     RPointerArray<CSenElement> sourceElements = aSource.ElementsL();
       
  1155     if (sourceElements.Count() > 0)
       
  1156         {
       
  1157         for (TInt i=0;i<sourceElements.Count(); i++)
       
  1158             {
       
  1159             CSenElement* pElement = sourceElements[i];
       
  1160             CSenElement* pNewElement =
       
  1161                                 CSenXmlElement::NewL(pElement->LocalName());
       
  1162             CleanupStack::PushL(pNewElement);
       
  1163             pNewElement->SetParent(this);
       
  1164             pNewElement->CopyFromL(*pElement);
       
  1165 
       
  1166             if(!ipElements)
       
  1167                 {
       
  1168                 ipElements = new (ELeave) RPointerArray<CSenElement>;
       
  1169                 }
       
  1170 
       
  1171 #ifdef EKA2
       
  1172             ipElements->AppendL(pNewElement);
       
  1173 #else
       
  1174             User::LeaveIfError(ipElements->Append(pNewElement));
       
  1175 #endif // EKA2
       
  1176             CleanupStack::Pop(pNewElement);
       
  1177             }
       
  1178         }
       
  1179     }
       
  1180 
       
  1181 EXPORT_C void CSenXmlElement::SetPrefixL(const TDesC8& aPrefix)
       
  1182     {
       
  1183     if (ipNamespaces && ipNamespaces->Find(ipNamespace) > -1)
       
  1184         {
       
  1185         //the namespace was locally declared
       
  1186 
       
  1187         // Check if element already has a namespace with given prefix
       
  1188         CSenNamespace* pNamespace = NULL;
       
  1189         TInt count(ipNamespaces->Count());
       
  1190         for (TInt i=0; i<count && pNamespace == NULL; i++)
       
  1191             {
       
  1192             pNamespace = (*ipNamespaces)[i];
       
  1193             if (pNamespace->Prefix() != aPrefix) 
       
  1194                 {
       
  1195                 pNamespace = NULL;
       
  1196                 }
       
  1197             }
       
  1198 
       
  1199         if (pNamespace)
       
  1200             {
       
  1201             // Update existing namespace
       
  1202             const TDesC8& uri = ipNamespace->URI();
       
  1203             pNamespace->SetUriL(uri);
       
  1204             ipNamespace = pNamespace;
       
  1205             }
       
  1206         else
       
  1207             {
       
  1208             if(ipElements) // are there any child elements?
       
  1209                 {
       
  1210                 if (ipNamespace->Prefix().Length() > 0 && ipElements->Count() > 0)
       
  1211                     {
       
  1212                     // there may be children that depend on the old prefix in e.g. attribute names
       
  1213                     const TDesC8& uri = ipNamespace->URI();
       
  1214                     ipNamespace = CSenNamespace::NewL(aPrefix, uri);
       
  1215 
       
  1216                     // append as new namespace
       
  1217                     ipNamespaces->Append(ipNamespace);
       
  1218                     }
       
  1219                 }
       
  1220             ipNamespace->SetPrefixL(aPrefix);
       
  1221             }
       
  1222         }
       
  1223     }
       
  1224 
       
  1225 EXPORT_C const CSenNamespace* CSenXmlElement::AddNamespaceL(
       
  1226                                                 CSenNamespace& aNewNamespace,
       
  1227                                                 TBool aCheckInParent)
       
  1228     {
       
  1229     const CSenNamespace* pNamespace =
       
  1230                         Namespace(aNewNamespace.Prefix(), aCheckInParent);
       
  1231 
       
  1232     if (pNamespace == NULL) // does not exist
       
  1233         {
       
  1234         CSenNamespace* pNewNamespace =
       
  1235             CSenNamespace::NewL(aNewNamespace.Prefix(), aNewNamespace.URI());
       
  1236 
       
  1237         // allocate array if not already reserved
       
  1238         if(!ipNamespaces)
       
  1239             {
       
  1240             ipNamespaces = new (ELeave) RPointerArray<CSenNamespace>;
       
  1241             }
       
  1242         ipNamespaces->Append(pNewNamespace);
       
  1243         pNamespace = pNewNamespace;
       
  1244         }
       
  1245     return pNamespace;
       
  1246     }
       
  1247 
       
  1248 EXPORT_C const CSenNamespace* CSenXmlElement::AddNamespaceL(
       
  1249                                                          const TDesC8& aPrefix,
       
  1250                                                          const TDesC8& aUri)
       
  1251     {
       
  1252     CSenNamespace* pNamespace = (CSenNamespace*)Namespace(aPrefix);
       
  1253 	if (!pNamespace)
       
  1254 		{
       
  1255 		if ( aUri.Length() > 0)
       
  1256 			{
       
  1257 				pNamespace = CSenNamespace::NewL(aPrefix, aUri);
       
  1258 			// allocate array if not already reserved
       
  1259 			if(!ipNamespaces)
       
  1260 				{
       
  1261 				ipNamespaces = new (ELeave) RPointerArray<CSenNamespace>;
       
  1262 				}
       
  1263 			ipNamespaces->Append(pNamespace);
       
  1264 			}
       
  1265 		}
       
  1266 	    else
       
  1267 	        {
       
  1268 	        pNamespace->SetUriL(aUri); // override current namespace URI with new one
       
  1269 	      
       
  1270 			}
       
  1271 
       
  1272     return pNamespace;
       
  1273     }
       
  1274 
       
  1275 EXPORT_C CSenElement* CSenXmlElement::DetachL()
       
  1276     {
       
  1277     if (!ipParent)
       
  1278         {
       
  1279         return NULL;
       
  1280         }
       
  1281 
       
  1282     // allocate array if not already reserved
       
  1283     if(!ipNamespaces)
       
  1284         {
       
  1285         ipNamespaces = new (ELeave) RPointerArray<CSenNamespace>;
       
  1286         }
       
  1287 
       
  1288     AddNamespaceMissingFromL(*ipNamespaces);
       
  1289 
       
  1290     // optimization: if nothing was added, free the array allocation
       
  1291     if(ipNamespaces && ipNamespaces->Count()==0)
       
  1292         {
       
  1293         ipNamespaces->ResetAndDestroy(); 
       
  1294         delete ipNamespaces; 
       
  1295                             
       
  1296         ipNamespaces = NULL;
       
  1297         }
       
  1298 
       
  1299     ipParent->RemoveElement(*this);
       
  1300     return this;
       
  1301     }
       
  1302 
       
  1303 void CSenXmlElement::AddNamespaceMissingFromL( RPointerArray<CSenNamespace>& aNamespaces )
       
  1304     {
       
  1305     // Add namespace of this element (possibly copied from parent)
       
  1306     // if that namespace is not already defined in
       
  1307     // aNamespaces array.
       
  1308     if ( ipNamespace && aNamespaces.Find(ipNamespace) == -1)
       
  1309         {
       
  1310         // Check if namespace declaration of this element can
       
  1311         // be found from aNamespaces array
       
  1312         TInt count(aNamespaces.Count());
       
  1313         TBool found(EFalse);
       
  1314         TInt i = 0;
       
  1315         for (; i<count; i++)
       
  1316             {
       
  1317             if ( aNamespaces[i]->URI() == ipNamespace->URI() && 
       
  1318                  aNamespaces[i]->Prefix() == ipNamespace->Prefix() )
       
  1319                 {
       
  1320                 found = ETrue;
       
  1321                 break;
       
  1322                 }
       
  1323             }
       
  1324         if ( !found )
       
  1325             {
       
  1326             //If not found then check in namespace usage array that namspace declaration 
       
  1327             //is present or not. If yes then continue without adding.
       
  1328             if((ipNamespaces && ipNamespaces->Find(ipNamespace) == -1) || !ipNamespaces)
       
  1329 	            {
       
  1330             
       
  1331 	            // Not found 
       
  1332 	            // => Create a copy of namespace declaration
       
  1333 	            //    and append it into aNamespaces array
       
  1334 	            CSenNamespace* pCopy =
       
  1335 	                    CSenNamespace::NewL(ipNamespace->Prefix(), ipNamespace->URI());
       
  1336 	            CleanupStack::PushL(pCopy);
       
  1337 	#ifdef EKA2
       
  1338 	            aNamespaces.AppendL(pCopy);
       
  1339 	#else
       
  1340 	            User::LeaveIfError(aNamespaces.Append(pCopy));
       
  1341 	#endif
       
  1342 	            CleanupStack::Pop(pCopy);
       
  1343 
       
  1344 	            // Change namespace object for this element to namespace object
       
  1345 	            // which can be found from aNamespaces array
       
  1346 	            ipNamespace = pCopy;
       
  1347 	            }
       
  1348             }
       
  1349         else
       
  1350             {
       
  1351             // Change namespace object for this element to namespace object
       
  1352             // which can be found from aNamespaces array
       
  1353             ipNamespace = aNamespaces[i];
       
  1354             }
       
  1355         }
       
  1356 
       
  1357     // Add namespaces from this element's attributes
       
  1358     // if those namespaces are not already defined in
       
  1359     // aNamespaces array.
       
  1360     if ( ipAttrs && ipAttrs->Count() > 0 )
       
  1361         {
       
  1362         TInt colon = -1;
       
  1363         const CSenNamespace* pNamespace = NULL;
       
  1364 
       
  1365         TInt count(ipAttrs->Count());
       
  1366         for(TInt i=0; i<count; i++)
       
  1367             {
       
  1368             CSenBaseAttribute* pAttribute = (*ipAttrs)[i];
       
  1369 
       
  1370             // Check namespace assigned to Name
       
  1371             colon = pAttribute->Name().Locate(':');
       
  1372             if ( colon > 0 )
       
  1373                 {
       
  1374                 pNamespace =
       
  1375                     Namespace(pAttribute->Name().Mid(0, colon), KNullDesC8);
       
  1376                 }
       
  1377             if ( pNamespace && (aNamespaces.Find(pNamespace) == -1) )
       
  1378                 {
       
  1379                 // Check if namespace declaration for handled attribute
       
  1380                 // _name_ can be found from aNamespaces array.
       
  1381                 TInt count(aNamespaces.Count());
       
  1382                 TBool found(EFalse);
       
  1383                 for (TInt i = 0; i<count; i++)
       
  1384                     {
       
  1385                     if ( aNamespaces[i]->URI() == pNamespace->URI() && 
       
  1386                          aNamespaces[i]->Prefix() == pNamespace->Prefix() )
       
  1387                         {
       
  1388                         found = ETrue;
       
  1389                         break;
       
  1390                         }
       
  1391                     }
       
  1392                 if ( !found )
       
  1393                     {
       
  1394 		            //If not found then check in namespace usage array that 
       
  1395 		            //namespace declaration is present or not. If yes then 
       
  1396 		            //continue without adding.
       
  1397 		            if((ipNamespaces && ipNamespaces->Find(pNamespace) == -1) || !ipNamespaces)
       
  1398 			            {
       
  1399                     
       
  1400 	                    // Not found 
       
  1401 	                    // => Create a copy of namespace declaration
       
  1402 	                    //    and append it into aNamespaces array
       
  1403 	                    CSenNamespace* pCopy =
       
  1404 	                            CSenNamespace::NewL(pNamespace->Prefix(),
       
  1405 	                                                pNamespace->URI());
       
  1406 	                    CleanupStack::PushL(pCopy);
       
  1407 	#ifdef EKA2
       
  1408 	                    aNamespaces.AppendL(pCopy);
       
  1409 	#else
       
  1410 	                    User::LeaveIfError(aNamespaces.Append(pCopy));
       
  1411 	#endif
       
  1412 	                    CleanupStack::Pop(pCopy);
       
  1413 			            }
       
  1414                     }
       
  1415                 }
       
  1416             pNamespace = NULL;
       
  1417 
       
  1418             // Check namespace assigned to Value
       
  1419             colon = pAttribute->Value().Locate(':');
       
  1420             if ( colon > 0 )
       
  1421                 {
       
  1422                 pNamespace =
       
  1423                     Namespace(pAttribute->Value().Mid(0, colon), KNullDesC8);
       
  1424                 }
       
  1425             if ( pNamespace && (aNamespaces.Find(pNamespace) == -1) )
       
  1426                 {
       
  1427                 // Check if namespace declaration for handled attribute
       
  1428                 // _value_ can be found from aNamespaces array.
       
  1429                 TInt count(aNamespaces.Count());
       
  1430                 TBool found(EFalse);
       
  1431                 for (TInt i = 0; i<count; i++)
       
  1432                     {
       
  1433                     if ( aNamespaces[i]->URI() == pNamespace->URI() && 
       
  1434                          aNamespaces[i]->Prefix() == pNamespace->Prefix() )
       
  1435                         {
       
  1436                         found = ETrue;
       
  1437                         break;
       
  1438                         }
       
  1439                     }
       
  1440                 if ( !found )
       
  1441                     {
       
  1442 					//If not found then check in namespace usage array that 
       
  1443 		            //namspace declaration is present or not.If yes then 
       
  1444 		            //continue without adding.
       
  1445 		            if(ipNamespaces && ipNamespaces->Find(pNamespace) == -1)
       
  1446 			            {
       
  1447 
       
  1448 	                    // Not found 
       
  1449 	                    // => Create a copy of namespace declaration
       
  1450 	                    //    and append it into aNamespaces array
       
  1451 	                    CSenNamespace* pCopy =
       
  1452 	                            CSenNamespace::NewL(pNamespace->Prefix(), 
       
  1453 	                                                pNamespace->URI());
       
  1454 	                    CleanupStack::PushL(pCopy);
       
  1455 	#ifdef EKA2
       
  1456 	                    aNamespaces.AppendL(pCopy);
       
  1457 	#else
       
  1458 	                    User::LeaveIfError(aNamespaces.Append(pCopy));
       
  1459 	#endif
       
  1460 	                    CleanupStack::Pop(pCopy);
       
  1461 			            }
       
  1462                     }
       
  1463                 }
       
  1464             pNamespace = NULL;
       
  1465             }
       
  1466         }
       
  1467 
       
  1468     if(ipElements && ipElements->Count() > 0)
       
  1469         {
       
  1470         TInt count(ipElements->Count());
       
  1471         for(TInt i=0; i<count; i++)
       
  1472             {
       
  1473             CSenXmlElement* pElement = (CSenXmlElement*) (*ipElements)[i];
       
  1474             pElement->AddNamespaceMissingFromL(aNamespaces);
       
  1475             }
       
  1476         }
       
  1477     }
       
  1478 
       
  1479 
       
  1480 EXPORT_C void CSenXmlElement::Set(const TDesC8& aNamespaceURI,
       
  1481                                    const TDesC8& aLocalName,
       
  1482                                    const TDesC8& aQName)
       
  1483     {
       
  1484     delete ipLocalName;
       
  1485     ipLocalName = NULL;
       
  1486     HBufC8* pTemp = aLocalName.Alloc();
       
  1487     if(pTemp)
       
  1488         {
       
  1489         ipLocalName = pTemp;
       
  1490         }
       
  1491 
       
  1492     TPtrC8 prefix(KNullDesC8);
       
  1493 
       
  1494     if(aQName != KNullDesC8)
       
  1495         {
       
  1496         TInt colon(KErrNotFound);
       
  1497         colon = aQName.Locate(':');
       
  1498         if(colon!=KErrNotFound)
       
  1499             {
       
  1500             prefix.Set(aQName.Left(colon));
       
  1501             }
       
  1502         }
       
  1503     TInt leaveCode(KErrNone);
       
  1504     TRAP(leaveCode, SetNamespaceL(prefix, aNamespaceURI);)
       
  1505     leaveCode=0;
       
  1506     
       
  1507     //if (err) ; 
       
  1508     }
       
  1509 
       
  1510 EXPORT_C CSenElement* CSenXmlElement::Child(TInt aIndex)
       
  1511     {
       
  1512     CSenElement* pElement = NULL;
       
  1513     if(ipElements && aIndex < ipElements->Count())
       
  1514         {
       
  1515         pElement = (CSenXmlElement*) (*ipElements)[aIndex];
       
  1516         }
       
  1517     return pElement;
       
  1518     }
       
  1519 
       
  1520 EXPORT_C TBool CSenXmlElement::ConsistsOfL(MSenElement& aCandidate)
       
  1521     {
       
  1522     // First check the names and namespaces
       
  1523     if (    aCandidate.LocalName() != this->LocalName()
       
  1524         ||  aCandidate.NamespaceURI() != this->NamespaceURI()
       
  1525         ||  aCandidate.NsPrefix() != this->NsPrefix()
       
  1526         )
       
  1527         {
       
  1528         return EFalse;
       
  1529         }
       
  1530 
       
  1531     // Then check content if it exists
       
  1532     if (aCandidate.HasContent())
       
  1533         {
       
  1534         if (aCandidate.Content() != this->Content())
       
  1535             {
       
  1536             return EFalse;  // Content doesn't match => no match
       
  1537             }
       
  1538         }
       
  1539 
       
  1540     // Then handle the children
       
  1541     RPointerArray<CSenElement>& children = aCandidate.ElementsL();
       
  1542     TInt childCount = children.Count();
       
  1543     TInt i=0;
       
  1544     while (i < childCount)
       
  1545         {
       
  1546         CSenElement* pMatchChild = children[i];
       
  1547         CSenElement* pChild = this->Element(pMatchChild->LocalName());
       
  1548         if (!pChild)
       
  1549             {
       
  1550             return EFalse;  // no child with same name found in children, 
       
  1551                             // => no match
       
  1552             }
       
  1553         else
       
  1554             {
       
  1555             if (!pChild->ConsistsOfL(*pMatchChild))
       
  1556                 {
       
  1557                 return EFalse; // a non matching child was found => No match
       
  1558                 }
       
  1559             }
       
  1560         i++;
       
  1561         }
       
  1562     return ETrue;
       
  1563     }
       
  1564 
       
  1565 void CSenXmlElement::Compress()
       
  1566     {
       
  1567     if(ipContentWriteStream)
       
  1568         {
       
  1569         ipContentWriteStream->Close();
       
  1570         delete ipContentWriteStream;
       
  1571         ipContentWriteStream = NULL;
       
  1572         }
       
  1573     if (ipContentBuf) ipContentBuf->Compress();
       
  1574     if(ipElements)
       
  1575         {
       
  1576         TInt count(ipElements->Count());
       
  1577 
       
  1578         for (TInt i = 0; i < count; i++)
       
  1579             {
       
  1580             CSenElement* pElement = (*ipElements)[i];
       
  1581             ((CSenXmlElement*)pElement)->Compress();
       
  1582             }
       
  1583         }
       
  1584     
       
  1585     }
       
  1586 
       
  1587 // New methods; problem: assume, that one cannot change CSenElement (abstract)
       
  1588 // class definition (virtual function tables); therefore one must be cautious
       
  1589 // and avoid class casting to internal element in base fragment layer(!) in
       
  1590 // order to access these methods! What if someone added a baseelement? -> crash
       
  1591 
       
  1592 // Optimized variant
       
  1593 // @return NULL if this element has no child elements
       
  1594 /*
       
  1595 RPointerArray<CSenElement>* CSenXmlElement::ElementsL()
       
  1596     {
       
  1597     return ipElements;
       
  1598     }
       
  1599 
       
  1600 // Optimized variant
       
  1601 //@return NULL if this element has no attributes 
       
  1602 RPointerArray<CSenBaseAttribute>* CSenXmlElement::AttributesL()
       
  1603     {
       
  1604     return ipAttrs;
       
  1605     }
       
  1606 
       
  1607 // Optimized variant
       
  1608 // @return RPointerArray<CSenNamespace>* or NULL if there are no attributes in this element
       
  1609 RPointerArray<CSenNamespace>& CSenXmlElement::NamespacesL()
       
  1610     {
       
  1611     return ipNamespaces;
       
  1612     }
       
  1613 */
       
  1614 
       
  1615 // end of file