|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Content handler implementation |
|
15 // |
|
16 |
|
17 #include <xml/parser.h> |
|
18 #include <xml/documentparameters.h> |
|
19 #include <xml/dom/xmlengdom.h> |
|
20 #include <xml/dom/xmlengdocument.h> |
|
21 #include "xmlengdomdefs.h" |
|
22 #include <xml/dom/xmlengbinarycontainer.h> |
|
23 #include <stdapis/libxml2/libxml2_globals.h> //xmlFree |
|
24 #include <xml/utils/xmlengxestd.h> |
|
25 #include "xmlengdomcontenthandler.h" |
|
26 |
|
27 xmlChar* xmlCharFromDesC8L(const TDesC8& aDesc) |
|
28 { |
|
29 if(!aDesc.Length()) |
|
30 { |
|
31 return NULL; |
|
32 } |
|
33 xmlChar* newContent = (xmlChar*)new(ELeave) TUint8[aDesc.Length() + 1]; |
|
34 *(Mem::Copy((TAny*)newContent, aDesc.Ptr(), aDesc.Length())) = 0; |
|
35 return newContent; |
|
36 } |
|
37 |
|
38 CXmlEngDOMContentHandler* CXmlEngDOMContentHandler::NewL(RXmlEngDocument& aDoc) |
|
39 { |
|
40 CXmlEngDOMContentHandler* self = new (ELeave) CXmlEngDOMContentHandler(aDoc); |
|
41 return self; |
|
42 } |
|
43 |
|
44 CXmlEngDOMContentHandler::~CXmlEngDOMContentHandler() |
|
45 { |
|
46 } |
|
47 |
|
48 CXmlEngDOMContentHandler::CXmlEngDOMContentHandler(RXmlEngDocument& aDoc): |
|
49 iDoc(aDoc) |
|
50 { |
|
51 iLastElement = iDoc; |
|
52 iTmpElement = TXmlEngElement(); |
|
53 } |
|
54 |
|
55 /** |
|
56 This method is a callback to indicate the start of the document. |
|
57 @param aDocParam Specifies the various parameters of the document. |
|
58 @param aDocParam.iCharacterSetName The character encoding of the document. |
|
59 @param aErrorCode is the error code. |
|
60 If this is not KErrNone then special action may be required. |
|
61 */ |
|
62 void CXmlEngDOMContentHandler::OnStartDocumentL(const RDocumentParameters& aDocParam, TInt aErrorCode) |
|
63 { |
|
64 if(aErrorCode) |
|
65 { |
|
66 return; |
|
67 } |
|
68 |
|
69 INTERNAL_DOCPTR(iDoc)->encoding = xmlCharFromDesC8L(aDocParam.CharacterSetName().DesC()); |
|
70 iTmpElement = iDoc.CreateDocumentElementL(_L8("fake")); |
|
71 } |
|
72 |
|
73 |
|
74 /** |
|
75 This method is a callback to indicate the end of the document. |
|
76 @param aErrorCode is the error code. |
|
77 If this is not KErrNone then special action may be required. |
|
78 */ |
|
79 void CXmlEngDOMContentHandler::OnEndDocumentL(TInt /*aErrorCode*/) |
|
80 { |
|
81 } |
|
82 |
|
83 |
|
84 /** |
|
85 This method is a callback to indicate an element has been parsed. |
|
86 @param aElement is a handle to the element's details. |
|
87 @param aAttributes contains the attributes for the element. |
|
88 @param aErrorCode is the error code. |
|
89 If this is not KErrNone then special action may be required. |
|
90 */ |
|
91 void CXmlEngDOMContentHandler::OnStartElementL(const RTagInfo& aElement, |
|
92 const RAttributeArray& aAttributes, |
|
93 TInt aErrorCode) |
|
94 { |
|
95 if(aErrorCode) |
|
96 { |
|
97 return; |
|
98 } |
|
99 |
|
100 TXmlEngElement element; |
|
101 if(iTmpElement.IsNull()) |
|
102 { |
|
103 element = iDoc.CreateElementL(aElement.LocalName().DesC(), |
|
104 aElement.Uri().DesC(), |
|
105 aElement.Prefix().DesC()); |
|
106 } |
|
107 else |
|
108 { |
|
109 element = iTmpElement; |
|
110 |
|
111 CXmlEngDOMContentHandler::RenameElementL( element, |
|
112 aElement.LocalName().DesC(), |
|
113 aElement.Uri().DesC(), |
|
114 aElement.Prefix().DesC() ); |
|
115 |
|
116 iTmpElement = TXmlEngElement(); |
|
117 } |
|
118 |
|
119 RArray <RAttribute> array = aAttributes; |
|
120 TInt size = array.Count(); |
|
121 RAttribute attr; |
|
122 |
|
123 for ( TInt i = 0; i < size; i++) |
|
124 { |
|
125 attr = array[i]; |
|
126 if(attr.Attribute().Prefix().DesC().Length()) |
|
127 { |
|
128 element.AddNewAttributeL(attr.Attribute().LocalName().DesC(), |
|
129 attr.Value().DesC(), |
|
130 attr.Attribute().Uri().DesC(), |
|
131 attr.Attribute().Prefix().DesC()); |
|
132 } |
|
133 else |
|
134 { |
|
135 element.AddNewAttributeL(attr.Attribute().LocalName().DesC(), |
|
136 attr.Value().DesC()); |
|
137 } |
|
138 } |
|
139 iLastElement.AppendChildL(element); |
|
140 iLastElement = element; |
|
141 } |
|
142 |
|
143 /** |
|
144 This method is a callback to indicate the end of the element has been reached. |
|
145 @param aElement is a handle to the element's details. |
|
146 @param aErrorCode is the error code. |
|
147 If this is not KErrNone then special action may be required. |
|
148 */ |
|
149 void CXmlEngDOMContentHandler::OnEndElementL(const RTagInfo& /*aElement*/, TInt aErrorCode) |
|
150 { |
|
151 if(aErrorCode) |
|
152 { |
|
153 return; |
|
154 } |
|
155 iLastElement = iLastElement.ParentNode(); |
|
156 } |
|
157 |
|
158 /** |
|
159 This method is a callback that sends the content of the element. |
|
160 Not all the content may be returned in one go. The data may be sent in chunks. |
|
161 When an OnEndElementL is received this means there is no more content to be sent. |
|
162 @param aBytes is the raw content data for the element. |
|
163 The client is responsible for converting the data to the |
|
164 required character set if necessary. |
|
165 In some instances the content may be binary and must not be converted. |
|
166 @param aErrorCode is the error code. |
|
167 If this is not KErrNone then special action may be required. |
|
168 */ |
|
169 void CXmlEngDOMContentHandler::OnContentL(const TDesC8& aBytes, TInt aErrorCode) |
|
170 { |
|
171 if(aErrorCode) |
|
172 { |
|
173 return; |
|
174 } |
|
175 iLastElement.AppendChildL(iDoc.CreateTextNodeL(aBytes)); |
|
176 } |
|
177 |
|
178 /** |
|
179 This method is a notification of the beginning of the scope of a prefix-URI Namespace mapping. |
|
180 This method is always called before the corresponding OnStartElementL method. |
|
181 @param aPrefix is the Namespace prefix being declared. |
|
182 @param aUri is the Namespace URI the prefix is mapped to. |
|
183 @param aErrorCode is the error code. |
|
184 If this is not KErrNone then special action may be required. |
|
185 */ |
|
186 void CXmlEngDOMContentHandler::OnStartPrefixMappingL(const RString& aPrefix, const RString& aUri, |
|
187 TInt aErrorCode) |
|
188 { |
|
189 if(aErrorCode) |
|
190 { |
|
191 return; |
|
192 } |
|
193 |
|
194 if(iTmpElement.IsNull()) |
|
195 { |
|
196 iTmpElement = iDoc.CreateElementL(_L8("fake")); |
|
197 } |
|
198 iTmpElement.AddNamespaceDeclarationL(aUri.DesC(),aPrefix.DesC()); |
|
199 } |
|
200 |
|
201 /** |
|
202 This method is a notification of the end of the scope of a prefix-URI mapping. |
|
203 This method is called after the corresponding DoEndElementL method. |
|
204 @param aPrefix is the Namespace prefix that was mapped. |
|
205 @param aErrorCode is the error code. |
|
206 If this is not KErrNone then special action may be required. |
|
207 */ |
|
208 void CXmlEngDOMContentHandler::OnEndPrefixMappingL(const RString& /*aPrefix*/, TInt /*aErrorCode*/) |
|
209 { |
|
210 } |
|
211 |
|
212 /** |
|
213 This method is a notification of ignorable whitespace in element content. |
|
214 @param aBytes are the ignored bytes from the document being parsed. |
|
215 @param aErrorCode is the error code. |
|
216 If this is not KErrNone then special action may be required. |
|
217 */ |
|
218 void CXmlEngDOMContentHandler::OnIgnorableWhiteSpaceL(const TDesC8& /*aBytes*/, TInt /*aErrorCode*/) |
|
219 { |
|
220 } |
|
221 |
|
222 /** |
|
223 This method is a notification of a skipped entity. If the parser encounters an |
|
224 external entity it does not need to expand it - it can return the entity as aName |
|
225 for the client to deal with. |
|
226 @param aName is the name of the skipped entity. |
|
227 @param aErrorCode is the error code. |
|
228 If this is not KErrNone then special action may be required. |
|
229 */ |
|
230 void CXmlEngDOMContentHandler::OnSkippedEntityL(const RString& /*aName*/, TInt /*aErrorCode*/) |
|
231 { |
|
232 |
|
233 } |
|
234 |
|
235 /** |
|
236 This method is a receive notification of a processing instruction. |
|
237 @param aTarget is the processing instruction target. |
|
238 @param aData is the processing instruction data. If empty none was supplied. |
|
239 @param aErrorCode is the error code. |
|
240 If this is not KErrNone then special action may be required. |
|
241 */ |
|
242 void CXmlEngDOMContentHandler::OnProcessingInstructionL(const TDesC8& aTarget, |
|
243 const TDesC8& aData, |
|
244 TInt aErrorCode) |
|
245 { |
|
246 if(aErrorCode) |
|
247 { |
|
248 return; |
|
249 } |
|
250 |
|
251 iLastElement.AppendChildL(iDoc.CreateProcessingInstructionL(aTarget,aData)); |
|
252 } |
|
253 |
|
254 /** |
|
255 * This method is a callback that sends the binary content of the element. |
|
256 * |
|
257 * @param aBytes is the raw binary data of the element |
|
258 * and must not be converted. |
|
259 * @param aErrorCode is the error code. If this is not KErrNone |
|
260 * then special action may be required. |
|
261 */ |
|
262 void CXmlEngDOMContentHandler::OnBinaryContentL(const TDesC8& aBytes, |
|
263 const TDesC8& aCid, |
|
264 TInt aErrorCode) |
|
265 { |
|
266 if(aErrorCode) |
|
267 { |
|
268 return; |
|
269 } |
|
270 |
|
271 iLastElement.AppendChildL(iDoc.CreateBinaryContainerL(aCid,aBytes)); |
|
272 } |
|
273 |
|
274 /** |
|
275 * This method is a callback that provides data container reference |
|
276 * |
|
277 * @param aContainer Container encapsulating binary data |
|
278 * @param aErrorCode is the error code. If this is not KErrNone |
|
279 * then special action may be required. |
|
280 */ |
|
281 void CXmlEngDOMContentHandler::OnDataContainerL( const TXmlEngDataContainer& aContainer, |
|
282 TInt aErrorCode) |
|
283 { |
|
284 if(aErrorCode) |
|
285 { |
|
286 return; |
|
287 } |
|
288 |
|
289 iLastElement.AppendChildL(aContainer); |
|
290 } |
|
291 |
|
292 /** |
|
293 This method indicates an error has occurred. |
|
294 @param aError is the error code |
|
295 */ |
|
296 void CXmlEngDOMContentHandler::OnError(TInt /*aErrorCode*/) |
|
297 { |
|
298 } |
|
299 |
|
300 /** |
|
301 This method obtains the interface matching the specified uid. |
|
302 @return 0 if no interface matching the uid is found. |
|
303 Otherwise, the this pointer cast to that interface. |
|
304 @param aUid the uid identifying the required interface. |
|
305 */ |
|
306 TAny* CXmlEngDOMContentHandler::GetExtendedInterface(const TInt32 aUid) |
|
307 { |
|
308 if (aUid == MXmlEngExtendedHandler::EExtInterfaceUid) |
|
309 { |
|
310 return static_cast<MXmlEngExtendedHandler*>(this); |
|
311 } |
|
312 return 0; |
|
313 } |
|
314 |
|
315 /** |
|
316 Renames TXmlEngElement nodes only. (static helper method) |
|
317 |
|
318 @param aElement element to rename |
|
319 @param aLocalName New name |
|
320 @param aNamespaceUri New namespace uri |
|
321 @param aPrefix New namespace prefix |
|
322 */ |
|
323 void CXmlEngDOMContentHandler::RenameElementL(TXmlEngElement& aElement, |
|
324 const TDesC8& aLocalName, |
|
325 const TDesC8& aNamespaceUri, |
|
326 const TDesC8& aPrefix ) |
|
327 { |
|
328 if ( !INTERNAL_NODEPTR(aElement)->type == XML_ELEMENT_NODE ) |
|
329 { |
|
330 User::Leave(KXmlEngErrWrongUseOfAPI); |
|
331 } |
|
332 |
|
333 TXmlEngNode::TXmlEngDOMNodeType type = aElement.NodeType(); |
|
334 if (type == TXmlEngNode::EElement) |
|
335 { |
|
336 SetNameL(aElement, aLocalName); |
|
337 if (aNamespaceUri.Length() || aPrefix.Length()) |
|
338 { |
|
339 TXmlEngElement nsElem = aElement.AsElement(); |
|
340 TXmlEngNamespace ns = nsElem.FindOrCreateNsDeclL(aNamespaceUri, aPrefix); |
|
341 INTERNAL_NODEPTR(aElement)->ns = INTERNAL_NSPTR(ns); |
|
342 } |
|
343 } |
|
344 } |
|
345 |
|
346 // --------------------------------------------------------------------------------------------- |
|
347 // Changes name of the element so that Name() on it will return new name |
|
348 // --------------------------------------------------------------------------------------------- |
|
349 void CXmlEngDOMContentHandler::SetNameL( TXmlEngElement& aElement, |
|
350 const TDesC8& aName ) |
|
351 { |
|
352 |
|
353 if ( !INTERNAL_NODEPTR(aElement) ) |
|
354 { |
|
355 User::Leave(KXmlEngErrNullNode); |
|
356 } |
|
357 const xmlChar* KOldName = INTERNAL_NODEPTR(aElement)->name; |
|
358 |
|
359 if ( aName.Length() <= 0 ) |
|
360 { |
|
361 User::Leave(KXmlEngErrWrongUseOfAPI); |
|
362 } |
|
363 INTERNAL_NODEPTR(aElement)->name = xmlCharFromDesC8L(aName); |
|
364 xmlFree((void *)KOldName); |
|
365 |
|
366 } |