diff -r 000000000000 -r 62f9d29f7211 webservices/wsxml/src/senxmlelement.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webservices/wsxml/src/senxmlelement.cpp Thu Jan 07 16:19:19 2010 +0200 @@ -0,0 +1,1615 @@ +/* +* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + + + + + + + +// INCLUDE FILES +#include "SenXmlElement.h" +#include "SenXmlConstants.h" // KSenColon, ++ +#include "SenXmlUtils.h" + +#include "senxmldebug.h" + +#ifdef SYMBIAN_SECURE_ECOM + // for 2.8, 3.0 or newer: + #include // needed for RAttributeArray +#else // for 2.6 or older + #include "Attribute.h" +#endif + +using namespace Xml; + +namespace + { + +// _LIT8(KColon, ":"); +// _LIT8(KLessThan, "<"); +// _LIT8(KGreaterThan, ">"); +// _LIT8(KSpace, " "); +// _LIT8(KDblQuot, "\""); +// _LIT8(KEqualsDblQuot, "=\""); +// _LIT8(KSlashGreaterThan, "/>"); +// _LIT8(KSenLessThanSlash, "BaseConstructL(aLocalName); + CleanupStack::Pop(); // pNew; + return pNew; + } + +EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri, + const TDesC8& aLocalName) + { + CSenXmlElement* pNew = new (ELeave) CSenXmlElement; + CleanupStack::PushL(pNew); + pNew->BaseConstructL(aNsUri, aLocalName); + CleanupStack::Pop(); // pNew; + return pNew; + } + +EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri, + const TDesC8& aLocalName, + const TDesC8& aQName) + { + CSenXmlElement* pNew = new (ELeave) CSenXmlElement; + CleanupStack::PushL(pNew); + pNew->BaseConstructL(aNsUri, aLocalName, aQName); + CleanupStack::Pop(); // pNew; + return pNew; + } + +EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri, + const TDesC8& aLocalName, + const TDesC8& aQName, + const RAttributeArray& apAttrs) + { + CSenXmlElement* pNew = new (ELeave) CSenXmlElement; + CleanupStack::PushL(pNew); + pNew->BaseConstructL(aNsUri, aLocalName, aQName, apAttrs); + CleanupStack::Pop(); // pNew; + return pNew; + } + + +EXPORT_C CSenXmlElement* CSenXmlElement::NewL(const TDesC8& aNsUri, + const TDesC8& aLocalName, + const TDesC8& aQName, + const RAttributeArray& apAttrs, + CSenElement& aParent) + { + CSenXmlElement* pNew = new (ELeave) CSenXmlElement; + CleanupStack::PushL(pNew); + pNew->BaseConstructL(aNsUri, aLocalName, aQName, apAttrs, aParent); + CleanupStack::Pop(); // pNew; + return pNew; + } + +EXPORT_C CSenXmlElement::CSenXmlElement() +: ipLocalName(NULL), + ipContentBuf(NULL), + ipParent(NULL), + ipNamespace(NULL) + { + } + +EXPORT_C CSenXmlElement::~CSenXmlElement() + { + if(ipContentWriteStream) + { + ipContentWriteStream->Close(); + delete ipContentWriteStream; + ipContentWriteStream = NULL; + } + + if(ipAttrs) + { + ipAttrs->ResetAndDestroy(); + delete ipAttrs; + ipAttrs = NULL; // not required + } + if(ipElements) + { + ipElements->ResetAndDestroy(); + delete ipElements; + ipElements = NULL; // not required + } + if(ipNamespaces) + { + ipNamespaces->ResetAndDestroy(); + delete ipNamespaces; + ipNamespaces = NULL; // not required + } + + delete ipLocalName; + ipLocalName = NULL; // not required + + + delete ipContentBuf; + ipContentBuf = NULL; // not required + + } + + + +EXPORT_C void CSenXmlElement::BaseConstructL(const TDesC8& aLocalName) + { + SenXmlUtils::LeaveOnInvalidElementNameL(aLocalName); + ipLocalName = aLocalName.AllocL(); + } + +EXPORT_C void CSenXmlElement::BaseConstructL(const TDesC8& aNsUri, + const TDesC8& aLocalName) + { + SenXmlUtils::LeaveOnInvalidElementNameL(aLocalName); + if(aNsUri.Length()>0) + { + SetNamespaceL(aNsUri); + } + ipLocalName = aLocalName.AllocL(); + } + +EXPORT_C void CSenXmlElement::BaseConstructL( const TDesC8& aNsUri, + const TDesC8& aLocalName, + const TDesC8& aQName) + { + SenXmlUtils::LeaveOnInvalidElementNameL(aLocalName); + SenXmlUtils::LeaveOnInvalidElementNameL(aQName); + ipLocalName = aLocalName.AllocL(); + TPtrC8 ptrPrefix(KNullDesC8); + + if (aQName.Length() > 0 ) + { + TInt colon = aQName.Locate(':'); + if (colon > 0) // Note: 0 also treated as no prefix + { + ptrPrefix.Set(aQName.Ptr(),colon); + } + } + + SetNamespaceL(ptrPrefix, aNsUri); + } + +EXPORT_C void CSenXmlElement::BaseConstructL( const TDesC8& aNsUri, + const TDesC8& aLocalName, + const TDesC8& aQName, + const RAttributeArray& apAttrs) + { + BaseConstructL(aNsUri, aLocalName, aQName); + SetAttributesL(apAttrs); + } + +EXPORT_C void CSenXmlElement::BaseConstructL( const TDesC8& aNsUri, + const TDesC8& aLocalName, + const TDesC8& aQName, + const RAttributeArray& apAttrs, + CSenElement& aParent ) + { + // parent must be set here at first line, because + // namespace setting dependends of it(!) + ipParent = &aParent; + + BaseConstructL(aNsUri, aLocalName, aQName); + SetAttributesL(apAttrs); + } + +EXPORT_C void CSenXmlElement::SetAttributesL(const RAttributeArray& apAttrs) + { + AddAttributesL(apAttrs); + } + + +EXPORT_C void CSenXmlElement::AddAttributesL(const RAttributeArray& apAttrs) + { + TInt count(apAttrs.Count()); + HBufC8* qName = NULL; + for(TInt i=0; i 0) + { + // we have an additional namespace declaration + AddNamespaceL(KNullDesC8(), aValue); + } + else + { + // this is a default name space declaration + SetNamespaceL(aValue); + } + + } + else if (aLocalName == NsPrefix()) + { + //we have a new declaration for the namespace of this element + SetNamespaceL(aLocalName, aValue); + } + else if(aQName.Find(KSenXmlNsAttNamePlusColon) == 0) + { + // we have an additional namespace declaration + AddNamespaceL(aLocalName, aValue); + } + else + { + // we have a real attribute! + CSenBaseAttribute* pAttribute = CSenBaseAttribute::NewL(aQName, + aLocalName, + aValue); + AddAttributeL(pAttribute); + } + return aValue; + } + + + +EXPORT_C const TDesC8& CSenXmlElement::AddAttributeL(const TDesC8& aAttrName, + const TDesC8& aValue) + { + // note, the aAttrName may be a qualified name or simply localname + // strip off the possible prefix from possible qualified name: + TPtrC8 localName = SenXmlUtils::LocalName(aAttrName); + return AddAttributeL(aAttrName, localName, aValue); + } + +// takes the ownership of aAttribute +EXPORT_C const TDesC8& CSenXmlElement::AddAttributeL( + CSenBaseAttribute* apAttribute) + { + CSenBaseAttribute* pOldAtt = FindAttr(apAttribute->Name()); + + // if attribute array is not yet allocated, instantiate here + if(!ipAttrs) + { + ipAttrs = new (ELeave) RPointerArray; + } + + if(!pOldAtt) + { + // transfrer the ownership to this class: + ipAttrs->Append(apAttribute); + return apAttribute->Value(); + } + else + { + pOldAtt->SetValueL(apAttribute->Value()); + delete apAttribute; + apAttribute = NULL; + return pOldAtt->Value(); + } + } + + +EXPORT_C CSenBaseAttribute* CSenXmlElement::FindAttr(const TDesC8& aName) + { + if(ipAttrs) + { + TInt count(ipAttrs->Count()); + for (TInt i = 0; i < count; i++) + { + CSenBaseAttribute* pAttribute = (*ipAttrs)[i]; + if(pAttribute->Name() == aName) + { + return pAttribute; + } + } + } + return NULL; + } + + +EXPORT_C TInt CSenXmlElement::IndexOfElement(const TDesC8& aNsUri, + const TDesC8& aLocalName) const + { + if(ipElements) + { + TInt count(ipElements->Count()); + + for (TInt i = 0; i < count; i++) + { + CSenElement* pElement = (*ipElements)[i]; + const TDesC8& nsUri = pElement->NamespaceURI(); + const TDesC8& localName = pElement->LocalName(); + if ((nsUri == aNsUri) && (localName == aLocalName)) + { + return i; + } + } + } + return KErrNotFound; + } + +EXPORT_C const TDesC8& CSenXmlElement::LocalName() const + { + if (ipLocalName == NULL) + { + return KNullDesC8(); + } + else + { + return *ipLocalName; + } + } + +EXPORT_C const TDesC8& CSenXmlElement::NamespaceURI() const + { + if (ipNamespace) + { + return ipNamespace->URI(); + } + else + { + return KNullDesC8(); + } + } + +EXPORT_C const TDesC8& CSenXmlElement::NsPrefix() const + { + if (!ipNamespace) + { + return KNullDesC8(); + } + else + { + return ipNamespace->Prefix(); + } + } + +EXPORT_C TBool CSenXmlElement::HasContent() const + { + if (!ipContentBuf) + { + return EFalse; + } + else + { + return (ipContentBuf->Size() > 0); + } + } + +EXPORT_C TPtrC8 CSenXmlElement::Content() const + { + if (!ipContentBuf) + { + return KNullDesC8(); + } + else + { + TPtrC8 p8 = ipContentBuf->Ptr(0); + return p8; + } + } + + +EXPORT_C HBufC* CSenXmlElement::ContentUnicodeL() const + { + HBufC* pRet = SenXmlUtils::ToUnicodeLC(Content()); + CleanupStack::Pop(); // pRet; + return pRet; + } + +EXPORT_C TPtrC8 CSenXmlElement::SetContentL(const TDesC8& aContent) + { + AllocContentBufL(); + if(ipContentBuf) + { + ipContentBuf->ResizeL(aContent.Size()); + ipContentBuf->Write(0, + TPtrC8(REINTERPRET_CAST(const TUint8*, aContent.Ptr()), + aContent.Size()) + ); + if(ipContentWriteStream) + { + // Reset stream + ipContentWriteStream->Open(*ipContentBuf); + } + } + return Content(); + } + +EXPORT_C RWriteStream& CSenXmlElement::ContentWriteStreamL() + { + AllocContentBufL(); + // Allocate stream + if(!ipContentWriteStream) + { + ipContentWriteStream = new (ELeave) RBufWriteStream; + } + ipContentWriteStream->Open(*ipContentBuf); + return *ipContentWriteStream; + } + +// NOTE: assumes(!) that the namespace is same(!) +// Optimization +// RPointerArray* or NULL if no elements have been added! +EXPORT_C RPointerArray& CSenXmlElement::ElementsL() + { + if(!ipElements) + { + ipElements = new (ELeave) RPointerArray; + } + return *ipElements; + } + +EXPORT_C TInt CSenXmlElement::ElementsL( + RPointerArray& aElementArray, + const TDesC8& aNsUri, + const TDesC8& aLocalName) + { + TInt retVal(KErrNotFound); + + if(ipElements) // return KErrNotFound, if zero elements have been added + { + TInt count(ipElements->Count()); + + if (count > 0) // return KErrNotFound, if owned array is empty + { + CSenElement* pElement = NULL; + for (TInt i=0; iLocalName()) && + (aNsUri == pElement->NamespaceURI()) ) + { + aElementArray.Append(pElement); + } + } + retVal = KErrNone; + } + } + return retVal; + } + +EXPORT_C TInt CSenXmlElement::ElementsL( + RPointerArray& aElementArray, + const TDesC8& aLocalName) + { + return ElementsL(aElementArray,NamespaceURI(),aLocalName); + } + +EXPORT_C const TDesC8* CSenXmlElement::AttrValue(const TDesC8& aName) + { + CSenBaseAttribute* pAttr = FindAttr(aName); + if (pAttr == NULL) + { + return NULL; + } + else + { + return &(pAttr->Value()); + } + } + +EXPORT_C void CSenXmlElement::AddAttrL(const TDesC8& aName, + const TDesC8& aValue) + { + CSenBaseAttribute* pAttr = FindAttr(aName); + if (!pAttr) + { + if(!ipAttrs) + { + ipAttrs = new (ELeave) RPointerArray; + } + + User::LeaveIfError(ipAttrs->Append(CSenBaseAttribute::NewL(aName, + aValue))); + } + else + { + pAttr->SetValueL(aValue); + } + } + +EXPORT_C CSenElement* CSenXmlElement::Parent() + { + return ipParent; + } + +EXPORT_C CSenElement* CSenXmlElement::SetParent(CSenElement* apParent) // IOP + { + if (apParent && ipParent != apParent) + { + ipParent = apParent; + if (!ipNamespace) + { + // check if there is a default namespace declared in the scope of + // the parent + const CSenNamespace* pParentNamespace = + ((CSenXmlElement*) ipParent)->Namespace(KNullDesC8,ETrue); + if (pParentNamespace && pParentNamespace->Prefix() == KNullDesC8) + { + ipNamespace = (CSenNamespace*)pParentNamespace; + } + } + else + { + //check if the parent already has a namespace for this element + // if so remove it from the local namespace table + const CSenNamespace* pNs = ipParent->Namespace(KNullDesC8, + ipNamespace->URI()); + if (pNs && pNs != ipNamespace) + { + if (ipNamespace->Compare(*pNs) || + ipNamespace->Prefix().Length() == 0) + { + //prefix is also identical or this element has no prefix + if(ipNamespaces) + { + TInt nsIndex = ipNamespaces->Find(ipNamespace); + if ( nsIndex != KErrNotFound) + { + ipNamespaces->Remove(nsIndex); + } + } + delete ipNamespace; + ipNamespace = NULL; + ipNamespace = (CSenNamespace*)pNs; + } + } + + } + } + return apParent; + } + +EXPORT_C MSenElement& CSenXmlElement::Root() + { + if (ipParent == NULL) + { + return *this; + } + else + { + return ipParent->Root(); + } + } + +EXPORT_C CSenElement* CSenXmlElement::Element(const TDesC8& aLocalName) + { + return Element(NamespaceURI(), aLocalName); + } + +EXPORT_C CSenElement* CSenXmlElement::Element(const TDesC8& aNsUri, + const TDesC8& aLocalName) + { + if(ipElements) + { + TInt idx = IndexOfElement(aNsUri, aLocalName); + if (idx < 0) + { + return NULL; + } + else + { + return (*ipElements)[idx]; + } + } + return NULL; + } + +EXPORT_C CSenElement* CSenXmlElement::CreateElementL(const TDesC8& aNsPrefix, + const TDesC8& aLocalName) + { + CSenElement* pNewElement = NULL; + + if (aNsPrefix.Length() > 0) + { + CSenNamespace* pNamespace = (CSenNamespace*)Namespace(aNsPrefix); + if (pNamespace) + { + HBufC8 *pQName = + HBufC8::NewLC(aNsPrefix.Length() + aLocalName.Length() +5); + TPtr8 ptr = pQName->Des(); + ptr.Append(aNsPrefix); + ptr.Append(':'); + ptr.Append(aLocalName); + pNewElement = + CSenXmlElement::NewL(pNamespace->URI(), aLocalName, *pQName); + CleanupStack::PopAndDestroy(); // pQName + } + } + else + { + pNewElement = CSenXmlElement::NewL(aLocalName); + } + + return pNewElement; // Returns NULL if required namespace can not be found! + } + +EXPORT_C CSenElement& CSenXmlElement::InsertElementL( + CSenElement& aElement, + const CSenElement& aBeforeElement) + { + TInt index(KErrNotFound); + + // allocate element array, if not already reserved + if(!ipElements) + { + ipElements = new (ELeave) RPointerArray; + } + else + { + // search only if array is not brand new + index = ipElements->Find(&aBeforeElement); + } + + if (index != KErrNotFound) + { + // repleace element + User::LeaveIfError(ipElements->Insert(&aElement,index)); + } + else + { + // add new element + User::LeaveIfError(ipElements->Append(&aElement)); + } + aElement.SetParent(this); + return aElement; + } + +EXPORT_C CSenElement& CSenXmlElement::AddElementL(CSenElement& aElement) + { + // allocate element array, if not already reserved + if(!ipElements) + { + ipElements = new (ELeave) RPointerArray; + } + + User::LeaveIfError(ipElements->Append(&aElement)); + aElement.SetParent(this); + return aElement; + } + +EXPORT_C CSenElement& CSenXmlElement::AddElementL(const TDesC8& aNsUri, + const TDesC8& aLocalName) + { + return AddElementL(*CSenXmlElement::NewL(aNsUri, aLocalName)); + } + +EXPORT_C CSenElement& CSenXmlElement::AddElementL( + const TDesC8& aNsUri, + const TDesC8& aLocalName, + const TDesC8& aQName + ) + { + return AddElementL(*CSenXmlElement::NewL(aNsUri, aLocalName, aQName)); + } + +EXPORT_C CSenElement& CSenXmlElement::AddElementL(const TDesC8& aLocalName) + { + return AddElementL(*CSenXmlElement::NewL(aLocalName)); + } + +EXPORT_C CSenElement* CSenXmlElement::RemoveElement(CSenElement& aElement) + { + CSenElement* pElement = NULL; + + if(ipElements) + { + TInt idx = ipElements->Find(&aElement); + if (idx >= 0) + { + pElement = (*ipElements)[idx]; + ipElements->Remove(idx); + pElement->SetParent(NULL); + return pElement; + } + } + return pElement; + } + +EXPORT_C CSenElement* CSenXmlElement::RemoveElement(const TDesC8& aNsUri, + const TDesC8& aLocalName) + { + TInt idx = IndexOfElement(aNsUri, aLocalName); + if (idx >= 0) + { + CSenElement* pElement = (*ipElements)[idx]; + ipElements->Remove(idx); + pElement->SetParent(NULL); + return pElement; + } + else + { + return NULL; + } + } + +EXPORT_C CSenElement* CSenXmlElement::RemoveElement(const TDesC8& aLocalName) + { + return RemoveElement(NamespaceURI(), aLocalName); + } + +EXPORT_C CSenElement* CSenXmlElement::ReplaceElementL(CSenElement& aElement) + { + CSenElement* pOldElement = + RemoveElement(aElement.NamespaceURI(), aElement.LocalName()); + CleanupStack::PushL(pOldElement); + AddElementL(aElement); + CleanupStack::Pop(); // pOldElement; + return pOldElement; + } + +EXPORT_C HBufC8* CSenXmlElement::AsXmlL() + { + CBufFlat *pBuf = CBufFlat::NewL(KFlatBufSize); + CleanupStack::PushL(pBuf); + TPtrC8 p = WriteToBufL(*pBuf); + HBufC8* pRet = p.AllocL(); + CleanupStack::PopAndDestroy(); // pBuf; + return pRet; + + } + +EXPORT_C HBufC* CSenXmlElement::AsXmlUnicodeL() + { + CBufFlat *pBuf = CBufFlat::NewL(KFlatBufSize); + CleanupStack::PushL(pBuf); + TPtrC8 p8 = WriteToBufL(*pBuf); + HBufC* pRet = SenXmlUtils::ToUnicodeLC(p8); + CleanupStack::Pop(); // pop pRet; + CleanupStack::PopAndDestroy(); // pBuf; + return pRet; + } + +EXPORT_C TPtrC8 CSenXmlElement::WriteToBufL(CBufBase& aBuf) + { + RBufWriteStream bufWs(aBuf); + CleanupClosePushL(bufWs); + this->WriteAsXMLToL(bufWs); + CleanupStack::PopAndDestroy(); // bufWs.Close(); + return aBuf.Ptr(0); + } + +EXPORT_C void CSenXmlElement::WriteAsXMLToL(RWriteStream& aWriteStream) + { + // Find out whether we should declare the namespace + TPtrC8 nsPrefix = NsPrefix(); + + // Element name + aWriteStream.WriteL(KSenLessThan); + if (nsPrefix.Length() > 0) + { + aWriteStream.WriteL(nsPrefix); + aWriteStream.WriteL(KSenColon); + } + aWriteStream.WriteL(*ipLocalName); + + + if ((ipAttrs && ipAttrs->Count() > 0) || + (ipNamespaces && ipNamespaces->Count() > 0)) + { + WriteNamespacesToL(aWriteStream); + WriteAttrsToL(aWriteStream); + } + + // Elements and content + if ((ipElements && ipElements->Count() > 0) || HasContent()) + { + aWriteStream.WriteL(KSenGreaterThan); + + // Body + WriteElementsToL(aWriteStream); + WriteContentToL(aWriteStream); + + // Closing element + aWriteStream.WriteL(KSenLessThanSlash); + if (nsPrefix.Length() > 0) + { + aWriteStream.WriteL(nsPrefix); + aWriteStream.WriteL(KSenColon); + } + aWriteStream.WriteL(*ipLocalName); + aWriteStream.WriteL(KSenGreaterThan); + } + else + { + aWriteStream.WriteL(KSenSlashGreaterThan); + } + } + +EXPORT_C void CSenXmlElement::WriteAttrToL(RWriteStream& aWriteStream, + const TDesC8& aName, + const TDesC8& aValue) + { + aWriteStream.WriteL(KSenSpace); + aWriteStream.WriteL(aName); + aWriteStream.WriteL(KSenEqualsDblQuot); + aWriteStream.WriteL(aValue); + aWriteStream.WriteL(KSenDblQuot); + } + +EXPORT_C void CSenXmlElement::WriteAttrsToL(RWriteStream& aWriteStream) + { + if(ipAttrs) + { + TInt count(ipAttrs->Count()); + for (TInt i = 0; i < count; i++) + { + WriteAttrToL(aWriteStream, (*ipAttrs)[i]->Name(), (*ipAttrs)[i]->Value()); + } + } + } + +EXPORT_C void CSenXmlElement::WriteNamespacesToL(RWriteStream& aWriteStream) + { + if(ipNamespaces) + { + CSenNamespace* ns = NULL; + TInt count = ipNamespaces->Count(); + for (TInt i=0; i < count; i++) + { + ns = (*ipNamespaces)[i]; + if (ns) + { + aWriteStream.WriteL(KSenSpaceXmlns); + if (ns->Prefix().Length() > 0) + { + aWriteStream.WriteL(KSenColon); + aWriteStream.WriteL(ns->Prefix()); + } + aWriteStream.WriteL(KSenEqualsDblQuot); + aWriteStream.WriteL(ns->URI()); + aWriteStream.WriteL(KSenDblQuot); + } + } + } + } + +EXPORT_C void CSenXmlElement::WriteElementsToL(RWriteStream& aWriteStream) + { + if(ipElements) + { + TInt elementCount(ipElements->Count()); + for (TInt i=0; iWriteAsXMLToL(aWriteStream); + } + } + } + +EXPORT_C void CSenXmlElement::WriteContentToL(RWriteStream& aWriteStream) + { + aWriteStream.WriteL(Content()); + } + +EXPORT_C MSenElement* CSenXmlElement::AsElement() + { + return this; + } + +EXPORT_C void CSenXmlElement::AllocContentBufL() + { + if(!ipContentBuf) + { + ipContentBuf = CBufFlat::NewL(KFlatBufSize); + } + } + +EXPORT_C void CSenXmlElement::SetNamespaceL(const TDesC8& aNsUri) + { + SetNamespaceL(KNullDesC8, aNsUri); + } + +EXPORT_C void CSenXmlElement::SetNamespaceL(const TDesC8& aNsPrefix, + const TDesC8& aNsUri) + { + if (aNsUri.Length() > 0) + { + ipNamespace = (CSenNamespace*) Namespace(aNsPrefix, aNsUri); + if (!ipNamespace) // not already defined + { + // allocate array if not already reserved + if(!ipNamespaces) + { + ipNamespaces = new (ELeave) RPointerArray; + } + ipNamespace = CSenNamespace::NewL(aNsPrefix, aNsUri); + ipNamespaces->Append(ipNamespace); + } + } + } + +EXPORT_C const CSenNamespace* CSenXmlElement::Namespace() + { + return ipNamespace; + } + +EXPORT_C const CSenNamespace* CSenXmlElement::Namespace( + const TDesC8& aNsPrefix) + { + return Namespace(aNsPrefix,ETrue); + } + +EXPORT_C const CSenNamespace* CSenXmlElement::Namespace( + const TDesC8& aNsPrefix, + const TBool aCheckInParent) + { + if (aNsPrefix.Length() == 0) return NULL; + + const CSenNamespace* pNamespace = NULL; + + if(ipNamespaces) + { + TInt count(ipNamespaces->Count()); + for (TInt i=0; iPrefix() != aNsPrefix) pNamespace = NULL; + } + } + } + + if (pNamespace == NULL && ipParent && aCheckInParent) + { + pNamespace = ipParent->Namespace(aNsPrefix); + } + + return pNamespace; + } + + +EXPORT_C const CSenNamespace* CSenXmlElement::Namespace( + const TDesC8& aNsPrefix, + const TDesC8& aUri) + { + // If prefix == NULL, then any prefix is ok + const CSenNamespace* pNs = NULL; + // Check if the namespace has already been declared + + if(ipNamespaces) + { + TInt count = ipNamespaces->Count(); + if (count != 0) + { + for (TInt i=0; iCompare(aNsPrefix, aUri)) + { + pNs = NULL; // not equal + } + else + { + break; + } + } + } + } + if (pNs == NULL && ipParent != NULL) + { + // if no namespace defined, but there is a parent, ask its namespace + pNs = ipParent->Namespace(aNsPrefix, aUri); + } + return pNs; + } + +EXPORT_C RPointerArray& CSenXmlElement::AttributesL() + { + // if attribute array is not yet allocated, instantiate here + if(!ipAttrs) + { + ipAttrs = new (ELeave) RPointerArray; + } + return *ipAttrs; + } + +EXPORT_C RPointerArray& CSenXmlElement::NamespacesL() + { + if(!ipNamespaces) + { + ipNamespaces = new (ELeave) RPointerArray; + } + return *ipNamespaces; + } + +EXPORT_C void CSenXmlElement::CopyFromL(CSenElement& aSource) + { + TPtrC8 sourceContent = aSource.Content(); + if (sourceContent.Length() > 0) + { + if (ipContentBuf == NULL) + { + SetContentL(sourceContent); + } + else + { + RBufWriteStream bufWs(*ipContentBuf); + CleanupClosePushL(bufWs); + bufWs.WriteL(sourceContent); + CleanupStack::PopAndDestroy(); // close bufWs + } + } + + RPointerArray sourceNamespaces = aSource.NamespacesL(); + if (sourceNamespaces.Count() > 0) + { + for (TInt i=0;iPrefix(),pNamespace->URI()); + CleanupStack::PushL(pNewNamespace); + + // allocate array if not already reserved + if(!ipNamespaces) + { + ipNamespaces = new (ELeave) RPointerArray; + } + +#ifdef EKA2 + ipNamespaces->AppendL(pNewNamespace); +#else + User::LeaveIfError(ipNamespaces->Append(pNewNamespace)); +#endif + CleanupStack::Pop(pNewNamespace); + } + } + SetNamespaceL(aSource.NsPrefix(), aSource.NamespaceURI()); + + RPointerArray sourceAttributes = aSource.AttributesL(); + if (sourceAttributes.Count() > 0) + { + for (TInt i=0;iName()); + if (pOriginal) + { + pOriginal->SetValueL(pBaseAttribute->Value()); + continue; + } + + CSenBaseAttribute* pNewBaseAttribute = + CSenBaseAttribute::NewL(pBaseAttribute->Name(), + pBaseAttribute->Value()); + CleanupStack::PushL(pNewBaseAttribute); + + // if attribute array is not yet allocated, instantiate here + if(!ipAttrs) + { + ipAttrs = new (ELeave) RPointerArray; + } + +#ifdef EKA2 + ipAttrs->AppendL(pNewBaseAttribute); +#else + User::LeaveIfError(ipAttrs->Append(pNewBaseAttribute)); +#endif + CleanupStack::Pop(pNewBaseAttribute); + } + } + + RPointerArray sourceElements = aSource.ElementsL(); + if (sourceElements.Count() > 0) + { + for (TInt i=0;iLocalName()); + CleanupStack::PushL(pNewElement); + pNewElement->SetParent(this); + pNewElement->CopyFromL(*pElement); + + if(!ipElements) + { + ipElements = new (ELeave) RPointerArray; + } + +#ifdef EKA2 + ipElements->AppendL(pNewElement); +#else + User::LeaveIfError(ipElements->Append(pNewElement)); +#endif // EKA2 + CleanupStack::Pop(pNewElement); + } + } + } + +EXPORT_C void CSenXmlElement::SetPrefixL(const TDesC8& aPrefix) + { + if (ipNamespaces && ipNamespaces->Find(ipNamespace) > -1) + { + //the namespace was locally declared + + // Check if element already has a namespace with given prefix + CSenNamespace* pNamespace = NULL; + TInt count(ipNamespaces->Count()); + for (TInt i=0; iPrefix() != aPrefix) + { + pNamespace = NULL; + } + } + + if (pNamespace) + { + // Update existing namespace + const TDesC8& uri = ipNamespace->URI(); + pNamespace->SetUriL(uri); + ipNamespace = pNamespace; + } + else + { + if(ipElements) // are there any child elements? + { + if (ipNamespace->Prefix().Length() > 0 && ipElements->Count() > 0) + { + // there may be children that depend on the old prefix in e.g. attribute names + const TDesC8& uri = ipNamespace->URI(); + ipNamespace = CSenNamespace::NewL(aPrefix, uri); + + // append as new namespace + ipNamespaces->Append(ipNamespace); + } + } + ipNamespace->SetPrefixL(aPrefix); + } + } + } + +EXPORT_C const CSenNamespace* CSenXmlElement::AddNamespaceL( + CSenNamespace& aNewNamespace, + TBool aCheckInParent) + { + const CSenNamespace* pNamespace = + Namespace(aNewNamespace.Prefix(), aCheckInParent); + + if (pNamespace == NULL) // does not exist + { + CSenNamespace* pNewNamespace = + CSenNamespace::NewL(aNewNamespace.Prefix(), aNewNamespace.URI()); + + // allocate array if not already reserved + if(!ipNamespaces) + { + ipNamespaces = new (ELeave) RPointerArray; + } + ipNamespaces->Append(pNewNamespace); + pNamespace = pNewNamespace; + } + return pNamespace; + } + +EXPORT_C const CSenNamespace* CSenXmlElement::AddNamespaceL( + const TDesC8& aPrefix, + const TDesC8& aUri) + { + CSenNamespace* pNamespace = (CSenNamespace*)Namespace(aPrefix); + if (!pNamespace) + { + if ( aUri.Length() > 0) + { + pNamespace = CSenNamespace::NewL(aPrefix, aUri); + // allocate array if not already reserved + if(!ipNamespaces) + { + ipNamespaces = new (ELeave) RPointerArray; + } + ipNamespaces->Append(pNamespace); + } + } + else + { + pNamespace->SetUriL(aUri); // override current namespace URI with new one + + } + + return pNamespace; + } + +EXPORT_C CSenElement* CSenXmlElement::DetachL() + { + if (!ipParent) + { + return NULL; + } + + // allocate array if not already reserved + if(!ipNamespaces) + { + ipNamespaces = new (ELeave) RPointerArray; + } + + AddNamespaceMissingFromL(*ipNamespaces); + + // optimization: if nothing was added, free the array allocation + if(ipNamespaces && ipNamespaces->Count()==0) + { + ipNamespaces->ResetAndDestroy(); + delete ipNamespaces; + + ipNamespaces = NULL; + } + + ipParent->RemoveElement(*this); + return this; + } + +void CSenXmlElement::AddNamespaceMissingFromL( RPointerArray& aNamespaces ) + { + // Add namespace of this element (possibly copied from parent) + // if that namespace is not already defined in + // aNamespaces array. + if ( ipNamespace && aNamespaces.Find(ipNamespace) == -1) + { + // Check if namespace declaration of this element can + // be found from aNamespaces array + TInt count(aNamespaces.Count()); + TBool found(EFalse); + TInt i = 0; + for (; iURI() == ipNamespace->URI() && + aNamespaces[i]->Prefix() == ipNamespace->Prefix() ) + { + found = ETrue; + break; + } + } + if ( !found ) + { + //If not found then check in namespace usage array that namspace declaration + //is present or not. If yes then continue without adding. + if((ipNamespaces && ipNamespaces->Find(ipNamespace) == -1) || !ipNamespaces) + { + + // Not found + // => Create a copy of namespace declaration + // and append it into aNamespaces array + CSenNamespace* pCopy = + CSenNamespace::NewL(ipNamespace->Prefix(), ipNamespace->URI()); + CleanupStack::PushL(pCopy); + #ifdef EKA2 + aNamespaces.AppendL(pCopy); + #else + User::LeaveIfError(aNamespaces.Append(pCopy)); + #endif + CleanupStack::Pop(pCopy); + + // Change namespace object for this element to namespace object + // which can be found from aNamespaces array + ipNamespace = pCopy; + } + } + else + { + // Change namespace object for this element to namespace object + // which can be found from aNamespaces array + ipNamespace = aNamespaces[i]; + } + } + + // Add namespaces from this element's attributes + // if those namespaces are not already defined in + // aNamespaces array. + if ( ipAttrs && ipAttrs->Count() > 0 ) + { + TInt colon = -1; + const CSenNamespace* pNamespace = NULL; + + TInt count(ipAttrs->Count()); + for(TInt i=0; iName().Locate(':'); + if ( colon > 0 ) + { + pNamespace = + Namespace(pAttribute->Name().Mid(0, colon), KNullDesC8); + } + if ( pNamespace && (aNamespaces.Find(pNamespace) == -1) ) + { + // Check if namespace declaration for handled attribute + // _name_ can be found from aNamespaces array. + TInt count(aNamespaces.Count()); + TBool found(EFalse); + for (TInt i = 0; iURI() == pNamespace->URI() && + aNamespaces[i]->Prefix() == pNamespace->Prefix() ) + { + found = ETrue; + break; + } + } + if ( !found ) + { + //If not found then check in namespace usage array that + //namespace declaration is present or not. If yes then + //continue without adding. + if((ipNamespaces && ipNamespaces->Find(pNamespace) == -1) || !ipNamespaces) + { + + // Not found + // => Create a copy of namespace declaration + // and append it into aNamespaces array + CSenNamespace* pCopy = + CSenNamespace::NewL(pNamespace->Prefix(), + pNamespace->URI()); + CleanupStack::PushL(pCopy); + #ifdef EKA2 + aNamespaces.AppendL(pCopy); + #else + User::LeaveIfError(aNamespaces.Append(pCopy)); + #endif + CleanupStack::Pop(pCopy); + } + } + } + pNamespace = NULL; + + // Check namespace assigned to Value + colon = pAttribute->Value().Locate(':'); + if ( colon > 0 ) + { + pNamespace = + Namespace(pAttribute->Value().Mid(0, colon), KNullDesC8); + } + if ( pNamespace && (aNamespaces.Find(pNamespace) == -1) ) + { + // Check if namespace declaration for handled attribute + // _value_ can be found from aNamespaces array. + TInt count(aNamespaces.Count()); + TBool found(EFalse); + for (TInt i = 0; iURI() == pNamespace->URI() && + aNamespaces[i]->Prefix() == pNamespace->Prefix() ) + { + found = ETrue; + break; + } + } + if ( !found ) + { + //If not found then check in namespace usage array that + //namspace declaration is present or not.If yes then + //continue without adding. + if(ipNamespaces && ipNamespaces->Find(pNamespace) == -1) + { + + // Not found + // => Create a copy of namespace declaration + // and append it into aNamespaces array + CSenNamespace* pCopy = + CSenNamespace::NewL(pNamespace->Prefix(), + pNamespace->URI()); + CleanupStack::PushL(pCopy); + #ifdef EKA2 + aNamespaces.AppendL(pCopy); + #else + User::LeaveIfError(aNamespaces.Append(pCopy)); + #endif + CleanupStack::Pop(pCopy); + } + } + } + pNamespace = NULL; + } + } + + if(ipElements && ipElements->Count() > 0) + { + TInt count(ipElements->Count()); + for(TInt i=0; iAddNamespaceMissingFromL(aNamespaces); + } + } + } + + +EXPORT_C void CSenXmlElement::Set(const TDesC8& aNamespaceURI, + const TDesC8& aLocalName, + const TDesC8& aQName) + { + delete ipLocalName; + ipLocalName = NULL; + HBufC8* pTemp = aLocalName.Alloc(); + if(pTemp) + { + ipLocalName = pTemp; + } + + TPtrC8 prefix(KNullDesC8); + + if(aQName != KNullDesC8) + { + TInt colon(KErrNotFound); + colon = aQName.Locate(':'); + if(colon!=KErrNotFound) + { + prefix.Set(aQName.Left(colon)); + } + } + TInt leaveCode(KErrNone); + TRAP(leaveCode, SetNamespaceL(prefix, aNamespaceURI);) + leaveCode=0; + + //if (err) ; + } + +EXPORT_C CSenElement* CSenXmlElement::Child(TInt aIndex) + { + CSenElement* pElement = NULL; + if(ipElements && aIndex < ipElements->Count()) + { + pElement = (CSenXmlElement*) (*ipElements)[aIndex]; + } + return pElement; + } + +EXPORT_C TBool CSenXmlElement::ConsistsOfL(MSenElement& aCandidate) + { + // First check the names and namespaces + if ( aCandidate.LocalName() != this->LocalName() + || aCandidate.NamespaceURI() != this->NamespaceURI() + || aCandidate.NsPrefix() != this->NsPrefix() + ) + { + return EFalse; + } + + // Then check content if it exists + if (aCandidate.HasContent()) + { + if (aCandidate.Content() != this->Content()) + { + return EFalse; // Content doesn't match => no match + } + } + + // Then handle the children + RPointerArray& children = aCandidate.ElementsL(); + TInt childCount = children.Count(); + TInt i=0; + while (i < childCount) + { + CSenElement* pMatchChild = children[i]; + CSenElement* pChild = this->Element(pMatchChild->LocalName()); + if (!pChild) + { + return EFalse; // no child with same name found in children, + // => no match + } + else + { + if (!pChild->ConsistsOfL(*pMatchChild)) + { + return EFalse; // a non matching child was found => No match + } + } + i++; + } + return ETrue; + } + +void CSenXmlElement::Compress() + { + if(ipContentWriteStream) + { + ipContentWriteStream->Close(); + delete ipContentWriteStream; + ipContentWriteStream = NULL; + } + if (ipContentBuf) ipContentBuf->Compress(); + if(ipElements) + { + TInt count(ipElements->Count()); + + for (TInt i = 0; i < count; i++) + { + CSenElement* pElement = (*ipElements)[i]; + ((CSenXmlElement*)pElement)->Compress(); + } + } + + } + +// New methods; problem: assume, that one cannot change CSenElement (abstract) +// class definition (virtual function tables); therefore one must be cautious +// and avoid class casting to internal element in base fragment layer(!) in +// order to access these methods! What if someone added a baseelement? -> crash + +// Optimized variant +// @return NULL if this element has no child elements +/* +RPointerArray* CSenXmlElement::ElementsL() + { + return ipElements; + } + +// Optimized variant +//@return NULL if this element has no attributes +RPointerArray* CSenXmlElement::AttributesL() + { + return ipAttrs; + } + +// Optimized variant +// @return RPointerArray* or NULL if there are no attributes in this element +RPointerArray& CSenXmlElement::NamespacesL() + { + return ipNamespaces; + } +*/ + +// end of file