1 // Created on: 2001-07-18
2 // Created by: Julia DOROVSKIKH
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 //AGV 150202: Add parameter isClearText to SetStringValue()
18 #include <LDOM_Text.hxx>
19 #include <TCollection_AsciiString.hxx>
20 #include <TCollection_ExtendedString.hxx>
21 #include <XmlObjMgt.hxx>
22 #include <XmlObjMgt_Document.hxx>
26 static const char aRefPrefix [] = "/document/label";
27 static const char aRefElem1 [] = "/label[@tag=";
28 static const char aRefElem2 [] = "]";
30 //=======================================================================
32 //purpose : return name of ID attribute to be used everywhere
33 //=======================================================================
35 const XmlObjMgt_DOMString& XmlObjMgt::IdString ()
37 static const LDOMString aString ("id");
41 //=======================================================================
42 //function : SetStringValue
43 //purpose : Add theData as the last child text node to theElement
44 //remark : Set isClearText to True if only you guarantee that the string
45 // does not contain '&', '<', '>', '\"', '\'', etc.
46 //=======================================================================
48 void XmlObjMgt::SetStringValue (XmlObjMgt_Element& theElement,
49 const XmlObjMgt_DOMString& theData,
50 const Standard_Boolean isClearText)
52 XmlObjMgt_Document aDocument = theElement.getOwnerDocument();
53 LDOM_Text aText = aDocument.createTextNode (theData);
54 if (isClearText) aText.SetValueClear();
55 theElement.appendChild (aText);
58 //=======================================================================
59 //function : GetStringValue
60 //purpose : returns the first child text node
61 //=======================================================================
63 XmlObjMgt_DOMString XmlObjMgt::GetStringValue
64 (const XmlObjMgt_Element& theElement)
66 XmlObjMgt_DOMString aString;
67 for (LDOM_Node aNode = theElement.getFirstChild();
69 aNode = aNode.getNextSibling())
71 if (aNode.getNodeType() == LDOM_Node::TEXT_NODE) {
72 aString = ((const LDOM_Text&)aNode).getData();
79 //=======================================================================
80 //function : SprintfExtStr
81 //purpose : Converts theString to hex printable representation and put it
82 // : to the out buffer
83 //=======================================================================
84 void SprintfExtStr(char * out, const TCollection_ExtendedString& theString) {
85 unsigned short * p = (unsigned short *)theString.ToExtString();
86 int len = theString.Length();
88 unsigned short mask[4] = {0xf000,0x0f00,0x00f0,0x000f};
90 for(int j = 0,k=3; j<4; j++,k--) {
91 unsigned short v = *(p+i) & mask[j];//x000
92 v = (unsigned short)(v >> (4*k));
101 out[4*theString.Length()] = 0x00;
103 //=======================================================================
104 //function : SetExtendedString
105 //purpose : Add text node to element and initialize it with string
106 //=======================================================================
108 Standard_Boolean XmlObjMgt::SetExtendedString
109 (XmlObjMgt_Element& theElement,
110 const TCollection_ExtendedString& theString)
112 TCollection_AsciiString anAString;
113 if (theString.IsAscii()) {
114 anAString = TCollection_AsciiString (theString, '?');
115 SetStringValue (theElement, anAString.ToCString());
117 const Standard_Integer aLen = theString.Length();
118 // const Standard_ExtCharacter * aString = theString.ToExtString();
119 char * buf0 = new char [4 * (aLen + 1) + 3];
120 Sprintf (&buf0[0], "##%04x", 0xfeff); // set UNICODE header
121 char * buf = &buf0[6];
122 // Standard_Integer i = 0;
123 // while (i <= (aLen - 4)) {
124 // Sprintf (&buf[i*4], "%04x%04x%04x%04x", aString[i], aString[i+1],
125 // aString[i+2], aString[i+3]);
128 // while (i < aLen) {
129 // Sprintf (&buf[i*4], "%04x", aString[i]);
132 // buf[4*aLen] = '\0';
134 SprintfExtStr(buf, theString);
135 SetStringValue (theElement, buf0);
138 return Standard_True;
141 //=======================================================================
142 //function : GetExtendedString
143 //purpose : Get the first text node in theElement and convert to ExtendedStr
144 //=======================================================================
146 Standard_Boolean XmlObjMgt::GetExtendedString
147 (const XmlObjMgt_Element& theElement,
148 TCollection_ExtendedString& theString)
150 theString = GetStringValue (theElement);
151 return Standard_True;
154 //=======================================================================
155 //function : GetTagEntryString
156 //purpose : Convert XPath expression (DOMString) into TagEntry string
157 // Returns False on error
158 //=======================================================================
160 Standard_Boolean XmlObjMgt::GetTagEntryString
161 (const XmlObjMgt_DOMString& theSource,
162 TCollection_AsciiString& theTagEntry)
165 const size_t aPrefixSize = sizeof(aRefPrefix) - 1;
166 const char * aSource = theSource.GetString();
167 if (strncmp (aSource, aRefPrefix, aPrefixSize))
168 return Standard_False;
170 // Beging aTagEntry string
172 (char *) Standard::Allocate (strlen(aSource)/2); // quite enough to hold it
173 char * aTagEntryPtr = aTagEntry + 1;
175 aSource += aPrefixSize;
177 // Find all individual tags in a loop
178 const size_t anElem1Size = sizeof(aRefElem1) - 1;
179 const size_t anElem2Size = sizeof(aRefElem2) - 1;
180 while (aSource[0] != '\0') {
181 // Check the first part of individual tag: "/label[@tag="
182 if (strncmp (aSource, aRefElem1, anElem1Size))
183 return Standard_False;
184 aSource += anElem1Size;
185 const char aQuote = aSource[0];
186 if (aQuote != '\'' && aQuote != '\"')
187 return Standard_False;
189 // Check the integer value of the tag
192 long aTagValue = strtol (&aSource[1], &aPtr, 10);
193 Standard_Integer aLen = (Standard_Integer)(aPtr - &aSource[1]);
194 if (aTagValue < 0 || aLen == 0 || aPtr[0] != aQuote ||
195 errno == ERANGE || errno == EINVAL)
196 return Standard_False;
197 aTagEntryPtr[0] = ':';
198 memcpy (&aTagEntryPtr[1], &aSource[1], aLen);
199 aTagEntryPtr += (aLen + 1);
201 // Check the final part of individual tag : "]"
202 if (strncmp (aPtr + 1, aRefElem2, anElem2Size))
203 return Standard_False;
204 aSource = aPtr + 1 + anElem2Size;
206 aTagEntryPtr[0] = '\0';
207 theTagEntry = aTagEntry;
208 Standard::Free (aTagEntry);
209 return Standard_True;
212 //=======================================================================
213 //function : SetTagEntryString
214 //purpose : Form an XPath string corresponding to the input TagEntry
215 //=======================================================================
217 void XmlObjMgt::SetTagEntryString (XmlObjMgt_DOMString& theTarget,
218 const TCollection_AsciiString& theTagEntry)
220 // Begin parsing theTagEntry
221 const char * aTagEntry = (const char*) theTagEntry.ToCString() + 1;
222 if (aTagEntry[-1] != '0')
225 // Count the number of tags in the label entry string
226 const char * aPtr = aTagEntry;
227 Standard_Integer aTagCount = 0;
228 while (* aPtr) if (* aPtr++ == ':') aTagCount ++;
230 // Create a buffer to accumulate the XPath reference
231 const size_t anElem1Size = sizeof(aRefElem1) - 1;
232 const size_t anElem2Size = sizeof(aRefElem2) - 1;
234 (char *) Standard::Allocate (sizeof(aRefPrefix) + aTagCount *
235 (anElem1Size + anElem2Size + 12));
236 memcpy (aTarget, aRefPrefix, sizeof (aRefPrefix) - 1);
237 char * aTargetPtr = aTarget + (sizeof (aRefPrefix) - 1);
240 // Check for the end-of-string; find the delimeter ':'
241 aPtr = strchr (aTagEntry, ':');
242 if (aPtr == NULL) break;
243 aTagEntry = aPtr + 1;
245 // Find the range of characters for an integer number
248 long aTagValue = strtol (aTagEntry, &ptr, 10);
249 Standard_Integer aTagSize = (Standard_Integer)(ptr - aTagEntry);
250 if (aTagValue < 0 || aTagSize == 0 ||
251 errno == ERANGE || errno == EINVAL)
254 // Add one XPath level to the expression in aTarget
255 memcpy (&aTargetPtr[0], aRefElem1, anElem1Size);
256 aTargetPtr[anElem1Size] = '\"';
257 memcpy (&aTargetPtr[anElem1Size+1], aTagEntry, aTagSize);
258 aTargetPtr[anElem1Size+aTagSize+1] = '\"';
259 memcpy (&aTargetPtr[anElem1Size+aTagSize+2],aRefElem2, anElem2Size);
260 aTargetPtr += (anElem1Size + aTagSize + anElem2Size + 2);
264 Standard::Free (aTarget);
267 //=======================================================================
268 //function : FindChildElement
270 //=======================================================================
271 XmlObjMgt_Element XmlObjMgt::FindChildElement
272 (const XmlObjMgt_Element& theSource,
273 const Standard_Integer theId)
275 LDOM_Node aNode = theSource.getFirstChild();
276 Standard_Integer anId;
277 while ( !aNode.isNull() )
279 if ( aNode.getNodeType() == LDOM_Node::ELEMENT_NODE )
281 LDOM_Element anElem = (LDOM_Element &) aNode;
282 if (anElem.getAttribute (IdString()).GetInteger(anId))
283 if (anId == theId) return anElem;
285 aNode = aNode.getNextSibling();
288 // find in all the document // to be done
289 // LDOM_Document aDoc = theSource.getOwnerDocument();
291 return LDOM_Element();
294 //=======================================================================
295 //function : FindChildByRef
297 //=======================================================================
299 XmlObjMgt_Element XmlObjMgt::FindChildByRef
300 (const XmlObjMgt_Element& theSource,
301 const XmlObjMgt_DOMString& theRefName)
303 Standard_Integer anID;
304 if (theSource.getAttribute (theRefName).GetInteger (anID))
305 return FindChildElement (theSource, anID);
306 return LDOM_Element();
310 //=======================================================================
311 //function : FindChildByName
313 //=======================================================================
314 XmlObjMgt_Element XmlObjMgt::FindChildByName
315 (const XmlObjMgt_Element& theSource,
316 const XmlObjMgt_DOMString& theName)
318 return theSource.GetChildByTagName(theName);
321 //=======================================================================
322 //function : GetInteger
324 //=======================================================================
325 Standard_Boolean XmlObjMgt::GetInteger (Standard_CString& theString,
326 Standard_Integer& theValue)
330 long aValue = strtol (theString, &ptr, 10);
331 if (ptr == theString || errno == ERANGE || errno == EINVAL)
332 return Standard_False;
333 theValue = Standard_Integer (aValue);
335 return Standard_True;
338 //=======================================================================
341 //=======================================================================
342 Standard_Boolean XmlObjMgt::GetReal (Standard_CString& theString,
343 Standard_Real& theValue)
347 double aValue = Strtod (theString, &ptr);
348 if (ptr == theString || errno == ERANGE || errno == EINVAL)
349 return Standard_False;
350 theValue = Standard_Real (aValue);
352 return Standard_True;
355 //=======================================================================
357 //purpose : Convert LDOMString to Real
358 //=======================================================================
359 Standard_Boolean XmlObjMgt::GetReal (const XmlObjMgt_DOMString& theString,
360 Standard_Real& theValue)
362 switch (theString.Type()) {
363 case LDOMBasicString::LDOM_NULL:
364 return Standard_False;
365 case LDOMBasicString::LDOM_Integer:
367 Standard_Integer anIntValue;
368 theString.GetInteger(anIntValue);
369 theValue = Standard_Real(anIntValue);
372 default: // LDOM_Ascii*
375 const char * aString = theString.GetString();
377 double aValue = Strtod (aString, &ptr);
378 if (ptr == aString || errno == ERANGE || errno == EINVAL)
379 return Standard_False;
380 theValue = Standard_Real (aValue);
383 return Standard_True;