1 // Created on: 2001-06-26
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2001-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
20 //AGV 140202: Replace(const char *) for (LDOMBasicString)=>myTagName
22 #include <LDOM_BasicElement.hxx>
23 #include <LDOM_BasicAttribute.hxx>
24 #include <LDOM_BasicText.hxx>
25 #include <LDOM_MemManager.hxx>
27 //=======================================================================
29 //purpose : construction in the Document's data pool
30 //=======================================================================
32 LDOM_BasicElement& LDOM_BasicElement::Create
34 const Standard_Integer aLen,
35 const Handle(LDOM_MemManager)& aDoc)
38 static LDOM_BasicElement aVoidElement;
39 aVoidElement = LDOM_BasicElement();
42 void * aMem = aDoc -> Allocate (sizeof(LDOM_BasicElement));
43 LDOM_BasicElement * aNewElem = new (aMem) LDOM_BasicElement;
45 Standard_Integer aHash;
46 // aDoc -> HashedAllocate (aString, strlen(aString), aNewElem -> myTagName);
47 aNewElem -> myTagName = aDoc -> HashedAllocate (aName, aLen, aHash);
49 aNewElem -> myNodeType = LDOM_Node::ELEMENT_NODE;
53 //=======================================================================
54 //function : RemoveNodes
56 //=======================================================================
58 void LDOM_BasicElement::RemoveNodes ()
60 const LDOM_BasicNode * aNode = (const LDOM_BasicNode *) myFirstChild;
62 const LDOM_BasicNode * aNext = aNode -> GetSibling();
63 switch (aNode -> getNodeType ()) {
64 case LDOM_Node::ELEMENT_NODE:
66 LDOM_BasicElement& anElement = * (LDOM_BasicElement *) aNode;
70 case LDOM_Node::ATTRIBUTE_NODE:
72 LDOM_BasicAttribute& anAttr = * (LDOM_BasicAttribute *) aNode;
76 case LDOM_Node::TEXT_NODE:
77 case LDOM_Node::COMMENT_NODE:
78 case LDOM_Node::CDATA_SECTION_NODE:
80 LDOM_BasicText& aTxt = * (LDOM_BasicText *) aNode;
91 //=======================================================================
92 //function : operator =
94 //=======================================================================
96 LDOM_BasicElement& LDOM_BasicElement:: operator = (const LDOM_NullPtr * aNull)
100 LDOM_BasicNode::operator= (aNull);
104 //=======================================================================
105 //function : LDOM_BasicElement
106 //purpose : Constructor
107 //=======================================================================
109 LDOM_BasicElement::LDOM_BasicElement (const LDOM_Element& anElement)
110 : LDOM_BasicNode (LDOM_Node::ELEMENT_NODE),
114 // LDOMString aNewTagName (anElement.getTagName(), anElement.myDocument);
115 // myTagName = aNewTagName;
116 const LDOM_BasicElement& anOther =
117 (const LDOM_BasicElement&) anElement.Origin();
118 myTagName = anOther.GetTagName();
121 //=======================================================================
122 //function : ~LDOM_BasicElement
123 //purpose : Destructor
124 //=======================================================================
126 LDOM_BasicElement::~LDOM_BasicElement ()
132 //=======================================================================
133 //function : GetLastChild
135 //=======================================================================
137 const LDOM_BasicNode * LDOM_BasicElement::GetLastChild () const
139 const LDOM_BasicNode * aNode = myFirstChild;
141 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
144 while (aNode -> mySibling) {
145 if (aNode -> mySibling -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
147 aNode = aNode -> mySibling;
153 //=======================================================================
154 //function : GetAttribute
156 //=======================================================================
158 const LDOM_BasicAttribute& LDOM_BasicElement::GetAttribute
159 (const LDOMBasicString& aName,
160 const LDOM_BasicNode * aLastCh) const
162 const LDOM_BasicNode * aNode;
164 aNode = aLastCh -> GetSibling ();
166 aNode = myFirstChild;
167 const char * aNameStr = aName.GetString();
169 if (aNode -> getNodeType () == LDOM_Node::ATTRIBUTE_NODE) {
170 const LDOM_BasicAttribute * anAttr = (const LDOM_BasicAttribute *) aNode;
171 if (!strcmp (aNameStr, anAttr -> GetName()))
174 aNode = aNode -> mySibling;
176 static const LDOM_BasicAttribute aNullAttribute;
177 return aNullAttribute;
180 //=======================================================================
181 //function : GetFirstAttribute
182 //purpose : private method
183 //=======================================================================
185 const LDOM_BasicAttribute * LDOM_BasicElement::GetFirstAttribute
186 (const LDOM_BasicNode *& theLastCh,
187 const LDOM_BasicNode **& thePrevNode) const
189 // Find the First Attribute as well as the Last Child among siblings
190 const LDOM_BasicNode * aFirstAttr;
191 const LDOM_BasicNode ** aPrevNode;
193 aFirstAttr = theLastCh -> mySibling;
194 aPrevNode = (const LDOM_BasicNode **) &(theLastCh -> mySibling);
196 if (aFirstAttr -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) break;
197 aPrevNode = (const LDOM_BasicNode **) & (aFirstAttr -> mySibling);
198 aFirstAttr = aFirstAttr -> mySibling;
201 aFirstAttr = myFirstChild;
202 aPrevNode = (const LDOM_BasicNode **) &myFirstChild;
204 if (aFirstAttr -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) break;
205 if (aFirstAttr -> isNull() == Standard_False) theLastCh = aFirstAttr;
206 aPrevNode = (const LDOM_BasicNode **) & (aFirstAttr -> mySibling);
207 aFirstAttr = aFirstAttr -> mySibling;
210 thePrevNode = aPrevNode;
211 return (LDOM_BasicAttribute *) aFirstAttr;
214 //=======================================================================
215 //function : AddAttribute
216 //purpose : Add or replace an attribute
217 //=======================================================================
219 const LDOM_BasicNode * LDOM_BasicElement::AddAttribute
220 (const LDOMBasicString& anAttrName,
221 const LDOMBasicString& anAttrValue,
222 const Handle(LDOM_MemManager)& aDocument,
223 const LDOM_BasicNode * aLastCh)
226 Standard_Integer aHash;
227 LDOM_BasicAttribute& anAttr =
228 LDOM_BasicAttribute::Create (anAttrName, aDocument, aHash);
229 anAttr.myValue = anAttrValue;
231 // Initialize the loop of attribute name search
232 const LDOM_BasicNode ** aPrNode;
233 const LDOM_BasicAttribute * aFirstAttr = GetFirstAttribute (aLastCh, aPrNode);
234 const char * aNameStr = anAttrName.GetString();
236 // Check attribute hash value against the current mask
237 const unsigned int anAttrMaskValue = aHash & (8*sizeof(myAttributeMask) - 1);
238 const unsigned long anAttributeMask = (1 << anAttrMaskValue);
240 anAttributeMask = 0xffffffff;
242 if ((myAttributeMask & anAttributeMask) == 0) {
243 // this is new attribute, OK
244 myAttributeMask |= anAttributeMask;
246 anAttr.SetSibling (aFirstAttr);
248 // this attribute may have already been installed
249 LDOM_BasicAttribute * aCurrentAttr = (LDOM_BasicAttribute *) aFirstAttr;
250 while (aCurrentAttr) {
251 if (aCurrentAttr -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
252 if (LDOM_MemManager::CompareStrings (aNameStr, aHash,
253 aCurrentAttr -> GetName())) {
254 aCurrentAttr -> SetValue (anAttrValue, aDocument);
257 aCurrentAttr = (LDOM_BasicAttribute *) aCurrentAttr -> mySibling;
259 if (aCurrentAttr == NULL) {
260 // this is new attribute, OK
262 anAttr.SetSibling (aFirstAttr);
268 //=======================================================================
269 //function : RemoveAttribute
270 //purpose : Find and delete an attribute from list
271 //=======================================================================
273 const LDOM_BasicNode * LDOM_BasicElement::RemoveAttribute
274 (const LDOMBasicString& aName,
275 const LDOM_BasicNode * aLastCh) const
277 // Check attribute hash value against the current mask
278 const char * const aNameStr = aName.GetString();
279 const Standard_Integer aHash =
280 LDOM_MemManager::Hash (aNameStr, strlen(aNameStr));
281 const unsigned int anAttrMaskValue = aHash & (8*sizeof(myAttributeMask) - 1);
282 const unsigned long anAttributeMask = (1 << anAttrMaskValue);
284 anAttributeMask = 0xffffffff;
286 if ((myAttributeMask & anAttributeMask) == 0) {
287 ; // maybe cause for exception
289 const LDOM_BasicNode ** aPrevNode; // dummy
290 const LDOM_BasicAttribute * anAttr = GetFirstAttribute (aLastCh, aPrevNode);
292 if (anAttr -> getNodeType () == LDOM_Node::ATTRIBUTE_NODE)
293 if (LDOM_MemManager::CompareStrings(aNameStr,aHash,anAttr->GetName())) {
297 anAttr = (const LDOM_BasicAttribute *) anAttr -> mySibling;
303 //=======================================================================
304 //function : RemoveChild
306 //=======================================================================
308 void LDOM_BasicElement::RemoveChild (const LDOM_BasicNode * aChild) const
310 const LDOM_BasicNode * aNode = myFirstChild;
311 const LDOM_BasicNode ** aPrevNode = (const LDOM_BasicNode **) &myFirstChild;
313 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
315 if (aNode == aChild) {
316 * aPrevNode = aNode -> GetSibling();
317 * (LDOM_BasicNode *) aChild = NULL;
320 aPrevNode = (const LDOM_BasicNode **) & (aNode -> mySibling);
321 aNode = aNode -> GetSibling();
323 // here may be the cause to throw an exception
326 //=======================================================================
327 //function : AppendChild
329 //=======================================================================
331 void LDOM_BasicElement::AppendChild (const LDOM_BasicNode * aChild,
332 const LDOM_BasicNode *& aLastChild) const
335 (const LDOM_BasicNode *&) aChild -> mySibling = aLastChild -> mySibling;
336 (const LDOM_BasicNode *&) aLastChild -> mySibling = aChild;
338 const LDOM_BasicNode * aNode = myFirstChild;
339 const LDOM_BasicNode ** aPrevNode = (const LDOM_BasicNode **) &myFirstChild;
341 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) {
342 (const LDOM_BasicNode *&) aChild -> mySibling = aNode;
345 aPrevNode = (const LDOM_BasicNode **) & (aNode -> mySibling);
346 aNode = aNode -> mySibling;
348 * aPrevNode = aChild;
353 //=======================================================================
354 //function : AddElementsByTagName
355 //purpose : Add to the List all sub-elements with the given name (recursive)
356 //=======================================================================
358 void LDOM_BasicElement::AddElementsByTagName
359 (LDOM_NodeList& aList, const LDOMBasicString& aTagName) const
361 const LDOM_BasicNode * aNode = myFirstChild;
362 const char * aTagString = aTagName.GetString();
364 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
366 if (aNode -> getNodeType() == LDOM_Node::ELEMENT_NODE) {
367 LDOM_BasicElement& anElement = * (LDOM_BasicElement *) aNode;
368 // if (anElement.GetTagName().equals(aTagName))
369 if (strcmp (anElement.GetTagName(), aTagString) == 0)
370 aList.Append (anElement);
371 anElement.AddElementsByTagName (aList, aTagName);
373 aNode = aNode -> GetSibling();
377 //=======================================================================
378 //function : AddAttributes
380 //=======================================================================
382 void LDOM_BasicElement::AddAttributes (LDOM_NodeList& aList,
383 const LDOM_BasicNode * aLastChild) const
385 const LDOM_BasicNode * aBNode;
387 aBNode = aLastChild -> GetSibling();
389 aBNode = GetFirstChild();
391 if (aBNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
392 aList.Append (* aBNode);
393 aBNode = aBNode -> GetSibling();
397 //=======================================================================
398 //function : ReplaceElement
399 //purpose : Copy data and children into this node from another one
400 // The only preserved data is mySibling
401 //=======================================================================
403 void LDOM_BasicElement::ReplaceElement
404 (const LDOM_BasicElement& anOtherElem,
405 const Handle(LDOM_MemManager)& aDocument)
407 myTagName = anOtherElem.GetTagName();
408 myAttributeMask = anOtherElem.myAttributeMask;
410 const LDOM_BasicNode * aBNode = anOtherElem.GetFirstChild ();
411 const LDOM_BasicNode * aLastChild = NULL;
413 // Loop on children (non-attributes)
414 for (; aBNode != NULL; aBNode = aBNode -> GetSibling()) {
415 if (aBNode -> isNull())
417 LDOM_BasicNode * aNewBNode;
418 const LDOM_Node::NodeType aNewNodeType = aBNode -> getNodeType();
419 switch (aNewNodeType) {
420 case LDOM_Node::ELEMENT_NODE:
422 const LDOM_BasicElement& aBNodeElem = *(const LDOM_BasicElement*)aBNode;
423 const char * aTagString = aBNodeElem.GetTagName();
424 LDOM_BasicElement& aNewBNodeElem =
425 LDOM_BasicElement::Create (aTagString, strlen(aTagString), aDocument);
426 aNewBNodeElem.ReplaceElement (aBNodeElem, aDocument); //reccur
427 aNewBNode = &aNewBNodeElem;
430 case LDOM_Node::ATTRIBUTE_NODE:
432 case LDOM_Node::TEXT_NODE:
433 case LDOM_Node::COMMENT_NODE:
434 case LDOM_Node::CDATA_SECTION_NODE:
436 const LDOM_BasicText& aBNodeText = * (const LDOM_BasicText *) aBNode;
437 aNewBNode = &LDOM_BasicText::Create (aNewNodeType,
438 LDOMString(aBNodeText.GetData(),
446 (const LDOM_BasicNode *&) aLastChild -> mySibling = aNewBNode;
448 (const LDOM_BasicNode *&) myFirstChild = aNewBNode;
449 (const LDOM_BasicNode *&) aLastChild = aNewBNode;
452 // Loop on attributes (in the end of the list of children)
454 LDOM_BasicNode * aLastAttr = (LDOM_BasicNode *) aLastChild;
455 for (; aBNode != NULL; aBNode = aBNode -> GetSibling()) {
456 Standard_Integer aHash;
457 if (aBNode -> isNull()) continue;
458 const LDOM_BasicAttribute * aBNodeAtt= (const LDOM_BasicAttribute *) aBNode;
459 LDOM_BasicAttribute * aNewAtt =
460 &LDOM_BasicAttribute::Create (aBNodeAtt -> GetName(), aDocument, aHash);
461 aNewAtt -> SetValue (aBNodeAtt->myValue, aDocument);
463 aLastAttr -> SetSibling (aNewAtt);
465 myFirstChild = aNewAtt;