1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012-2014 - Scilab Enterprises - Calixte DENIZET
4 *
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
6 *
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
13 *
14 */
15
16 #include "XMLObject.hxx"
17 #include "XMLElement.hxx"
18 #include "XMLDocument.hxx"
19 #include "XMLNodeList.hxx"
20 #include "XMLNs.hxx"
21 #include "XMLAttr.hxx"
22 #include "VariableScope.hxx"
23
24 extern "C"
25 {
26 extern const char *nodes_type[];
27 }
28
29 namespace org_modules_xml
30 {
31
XMLElement(const XMLDocument & _doc,xmlNode * _node)32 XMLElement::XMLElement(const XMLDocument & _doc, xmlNode * _node): XMLObject(), allocated(false), doc(_doc)
33 {
34 node = _node;
35 scope->registerPointers(node, this);
36 scilabType = XMLELEMENT;
37 id = scope->getVariableId(*this);
38 }
39
XMLElement(const XMLDocument & _doc,const char * name)40 XMLElement::XMLElement(const XMLDocument & _doc, const char *name): XMLObject(), allocated(true), doc(_doc)
41 {
42 node = xmlNewNode(0, (const xmlChar *)name);
43 scope->registerPointers(node, this);
44 scilabType = XMLELEMENT;
45 id = scope->getVariableId(*this);
46 }
47
~XMLElement()48 XMLElement::~XMLElement()
49 {
50 scope->unregisterPointer(node);
51 scope->removeId(id);
52
53 if (allocated)
54 {
55 xmlFreeNode(node);
56 }
57 }
58
getRealXMLPointer() const59 void *XMLElement::getRealXMLPointer() const
60 {
61 return static_cast < void *>(node);
62 }
63
remove() const64 void XMLElement::remove() const
65 {
66 XMLNodeList *obj = 0;
67
68 if (node->parent && node->parent->children)
69 {
70 obj = scope->getXMLNodeListFromLibXMLPtr(node->parent->children);
71 if (obj && node->parent->children == node)
72 {
73 // node->parent->children == node => we remove the first child so parent->children
74 // needs to be correctly re-linked.
75 obj->removeElementAtPosition(1);
76 return;
77 }
78 }
79
80 xmlUnlinkNode(node);
81 xmlFreeNode(node);
82
83 if (obj)
84 {
85 obj->revalidateSize();
86 }
87 }
88
getXMLObjectParent() const89 const XMLObject *XMLElement::getXMLObjectParent() const
90 {
91 return &doc;
92 }
93
getNodeContent() const94 const char *XMLElement::getNodeContent() const
95 {
96 return (const char *)xmlNodeGetContent(node);
97 }
98
setNodeName(const std::string & name) const99 void XMLElement::setNodeName(const std::string & name) const
100 {
101 xmlNodeSetName(node, (const xmlChar *)name.c_str());
102 }
103
setNodeNameSpace(const XMLNs & ns) const104 void XMLElement::setNodeNameSpace(const XMLNs & ns) const
105 {
106 xmlNs *n = ns.getRealNs();
107 if (n)
108 {
109 if (!n->prefix || !xmlSearchNs(doc.getRealDocument(), node, n->prefix))
110 {
111 n = xmlNewNs(node, (const xmlChar *)ns.getHref(), (const xmlChar *)ns.getPrefix());
112 }
113 xmlSetNs(node, n);
114 }
115 }
116
setNodeContent(const std::string & content) const117 void XMLElement::setNodeContent(const std::string & content) const
118 {
119 xmlNodeSetContent(node, (const xmlChar *)content.c_str());
120 }
121
setAttributes(const XMLAttr & attrs) const122 void XMLElement::setAttributes(const XMLAttr & attrs) const
123 {
124 xmlNode *attrNode = attrs.getElement().getRealNode();
125 if (node != attrNode)
126 {
127 xmlFreePropList(node->properties);
128 node->properties = 0;
129 xmlCopyPropList(node, attrNode->properties);
130 }
131 }
132
setAttributeValue(const char ** prefix,const char ** name,const char ** value,int size) const133 void XMLElement::setAttributeValue(const char **prefix, const char **name, const char **value, int size) const
134 {
135 XMLAttr::setAttributeValue(node, prefix, name, value, size);
136 }
137
setAttributeValue(const char ** name,const char ** value,int size) const138 void XMLElement::setAttributeValue(const char **name, const char **value, int size) const
139 {
140 XMLAttr::setAttributeValue(node, name, value, size);
141 }
142
append(const XMLElement & elem) const143 void XMLElement::append(const XMLElement & elem) const
144 {
145 XMLNodeList * list = 0;
146 xmlNode *cpy = xmlCopyNode(elem.getRealNode(), 1);
147 xmlUnlinkNode(cpy);
148 xmlAddChild(node, cpy);
149
150 list = scope->getXMLNodeListFromLibXMLPtr(node->children);
151 if (list)
152 {
153 list->incrementSize();
154 }
155 }
156
setChildren(const XMLElement & elem) const157 void XMLElement::setChildren(const XMLElement & elem) const
158 {
159 xmlNode *n = elem.getRealNode();
160 if (n && n->parent != node)
161 {
162 xmlNode *cpy = xmlCopyNode(n, 1);
163 xmlUnlinkNode(cpy);
164 xmlUnlinkNode(node->children);
165 xmlFreeNodeList(node->children);
166 node->children = 0;
167 xmlAddChild(node, cpy);
168 }
169 }
170
setChildren(const XMLNodeList & list) const171 void XMLElement::setChildren(const XMLNodeList & list) const
172 {
173 xmlNode *n = list.getRealNode();
174 if (n && n->parent != node)
175 {
176 xmlNode *cpy = xmlCopyNodeList(n);
177 xmlUnlinkNode(node->children);
178 xmlFreeNodeList(node->children);
179 node->children = 0;
180 xmlAddChildList(node, cpy);
181 }
182 }
183
setChildren(const std::string & xmlCode) const184 void XMLElement::setChildren(const std::string & xmlCode) const
185 {
186 std::string error;
187 XMLDocument document = XMLDocument(xmlCode, false, &error);
188
189 if (error.empty())
190 {
191 setChildren(*document.getRoot());
192 }
193 else
194 {
195 xmlNode *n = xmlNewText((xmlChar *) xmlCode.c_str());
196
197 setChildren(XMLElement(doc, n));
198 }
199 }
200
addNamespace(const XMLNs & ns) const201 void XMLElement::addNamespace(const XMLNs & ns) const
202 {
203 xmlNewNs(node, (const xmlChar *)ns.getHref(), (const xmlChar *)ns.getPrefix());
204 }
205
getNamespaceByPrefix(const char * prefix) const206 const XMLNs *XMLElement::getNamespaceByPrefix(const char *prefix) const
207 {
208 xmlNs *ns = xmlSearchNs(doc.getRealDocument(), node, (const xmlChar *)prefix);
209 XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(ns);
210 if (obj)
211 {
212 return static_cast < XMLNs * >(obj);
213 }
214
215 return new XMLNs(*this, ns);
216 }
217
getNamespaceByHref(const char * href) const218 const XMLNs *XMLElement::getNamespaceByHref(const char *href) const
219 {
220 xmlNs *ns = xmlSearchNsByHref(doc.getRealDocument(), node, (const xmlChar *)href);
221 XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(ns);
222 if (obj)
223 {
224 return static_cast < XMLNs * >(obj);
225 }
226
227 return new XMLNs(*this, ns);
228 }
229
dump(bool indent) const230 const std::string XMLElement::dump(bool indent) const
231 {
232 xmlBufferPtr buffer = xmlBufferCreate();
233 xmlNodeDump(buffer, doc.getRealDocument(), node, 0, indent ? 1 : 0);
234 std::string str = std::string((const char *)buffer->content);
235 xmlBufferFree(buffer);
236
237 return str;
238 }
239
toString() const240 const std::string XMLElement::toString() const
241 {
242 std::ostringstream oss;
243 std::string ns = "";
244 std::string prefix = "";
245
246 if (node->ns)
247 {
248 if (node->ns->href)
249 {
250 ns = std::string((const char *)node->ns->href);
251 }
252
253 if (node->ns->prefix)
254 {
255 prefix = std::string((const char *)node->ns->prefix);
256 }
257 }
258
259 oss << "XML Element" << std::endl
260 << "name: " << getNodeName() << std::endl
261 << "namespace: XML Namespace" << std::endl
262 << " href: " << ns << std::endl
263 << " prefix: " << prefix << std::endl
264 << "type: " << nodes_type[getNodeType() - 1] << std::endl
265 << "parent: XML Element" << std::endl
266 << "attributes: [1 x " << XMLAttr::getSize(node->properties) << "]" << std::endl
267 << "children: [1 x " << XMLNodeList::getNodeListSize(node->children) << "]" << std::endl
268 << "content: ..." << std::endl
269 << "line: " << node->line;
270
271 return oss.str();
272 }
273
getDefinitionLine() const274 int XMLElement::getDefinitionLine() const
275 {
276 return node->line;
277 }
278
getNodeNameSpace() const279 const XMLNs *XMLElement::getNodeNameSpace() const
280 {
281 if (node->ns)
282 {
283 XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(node->ns);
284 if (obj)
285 {
286 return static_cast < XMLNs * >(obj);
287 }
288
289 return new XMLNs(*this, node->ns);
290 }
291 else
292 {
293 return 0;
294 }
295 }
296
getChildren() const297 const XMLNodeList *XMLElement::getChildren() const
298 {
299 XMLNodeList *obj = scope->getXMLNodeListFromLibXMLPtr(node->children);
300 if (obj)
301 {
302 return obj;
303 }
304
305 return new XMLNodeList(doc, node);
306 }
307
getAttributes() const308 const XMLAttr *XMLElement::getAttributes() const
309 {
310 XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(node->properties);
311 if (obj)
312 {
313 return static_cast < XMLAttr * >(obj);
314 }
315
316 return new XMLAttr(*this);
317 }
318
getParentElement() const319 const XMLElement *XMLElement::getParentElement() const
320 {
321 if (node->parent && node->parent->type == XML_ELEMENT_NODE)
322 {
323 XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(node->parent);
324 if (obj)
325 {
326 return static_cast < XMLElement * >(obj);
327 }
328
329 return new XMLElement(doc, node->parent);
330 }
331 else
332 {
333 return 0;
334 }
335 }
336 }
337