198d5ce883d2ff73930aa04f351acfae004a8f60
[shibboleth/cpp-xmltooling.git] / xmltooling / util / XMLHelper.h
1 /*
2  *  Copyright 2001-2011 Internet2
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file xmltooling/util/XMLHelper.h
19  *
20  * A helper class for working with W3C DOM objects.
21  */
22
23 #ifndef __xmltooling_xmlhelper_h__
24 #define __xmltooling_xmlhelper_h__
25
26 #include <xmltooling/unicode.h>
27
28 #include <map>
29 #include <iostream>
30 #include <xercesc/dom/DOM.hpp>
31
32 namespace xmltooling {
33
34     class XMLTOOL_API QName;
35     class XMLTOOL_API XMLObject;
36
37     /**
38      * RAII wrapper for Xerces resources.
39      */
40     template<class T> class XercesJanitor
41     {
42         MAKE_NONCOPYABLE(XercesJanitor);
43         T* m_held;
44     public:
45         /**
46          * Constructor
47          *
48          * @param resource  object to release when leaving scope
49          */
50         XercesJanitor(T* resource) : m_held(resource) {}
51
52         ~XercesJanitor() {
53             if (m_held)
54                 m_held->release();
55         }
56
57         /**
58          * Returns resource held by this object.
59          *
60          * @return  the resource held or nullptr
61          */
62         T* get() {
63             return m_held;
64         }
65
66         /**
67          * Returns resource held by this object.
68          *
69          * @return  the resource held or nullptr
70          */
71         T* operator->() {
72             return m_held;
73         }
74
75         /**
76          * Returns resource held by this object and releases it to the caller.
77          *
78          * @return  the resource held or nullptr
79          */
80         T* release() {
81             T* ret=m_held;
82             m_held=nullptr;
83             return ret;
84         }
85     };
86
87     /**
88      * A helper class for working with W3C DOM objects.
89      */
90     class XMLTOOL_API XMLHelper
91     {
92     public:
93         /**
94          * Checks if the given element has an xsi:type defined for it
95          *
96          * @param e the DOM element
97          * @return true if there is a type, false if not
98          */
99         static bool hasXSIType(const xercesc::DOMElement* e);
100
101         /**
102          * Gets the XSI type for a given element if it has one.
103          *
104          * @param e the element
105          * @return the type or null
106          */
107         static QName* getXSIType(const xercesc::DOMElement* e);
108
109         /**
110          * Gets the ID attribute of a DOM element.
111          *
112          * @param domElement the DOM element
113          * @return the ID attribute or null if there isn't one
114          */
115         static xercesc::DOMAttr* getIdAttribute(const xercesc::DOMElement* domElement);
116
117         /**
118          * Attempts to locate an XMLObject from this point downward in the tree whose
119          * XML ID matches the supplied value.
120          *
121          * @param tree  root of tree to search
122          * @param id    ID value to locate
123          * @return XMLObject in the tree with a matching ID value, or nullptr
124          */
125         static const XMLObject* getXMLObjectById(const XMLObject& tree, const XMLCh* id);
126
127         /**
128          * Attempts to locate an XMLObject from this point downward in the tree whose
129          * XML ID matches the supplied value.
130          *
131          * @param tree  root of tree to search
132          * @param id    ID value to locate
133          * @return XMLObject in the tree with a matching ID value, or nullptr
134          */
135         static XMLObject* getXMLObjectById(XMLObject& tree, const XMLCh* id);
136
137         /**
138          * Returns the set of non-visibly-used namespace declarations found in a tree.
139          * <p>Each member of the set is a prefix/URI pair.
140          *
141          * @param tree      root of tree to search
142          * @param prefixes  container to store declarations
143          */
144         static void getNonVisiblyUsedPrefixes(const XMLObject& tree, std::map<xstring,xstring>& prefixes);
145
146         /**
147          * Gets the QName for the given DOM node.
148          *
149          * @param domNode the DOM node
150          * @return the QName for the element or null if the element was null
151          */
152         static QName* getNodeQName(const xercesc::DOMNode* domNode);
153
154         /**
155          * @deprecated
156          * Constructs a QName from an attribute's value.
157          *
158          * @param attribute the attribute with a QName value
159          * @return a QName from an attribute's value, or null if the given attribute is null
160          */
161         static QName* getAttributeValueAsQName(const xercesc::DOMAttr* attribute);
162
163         /**
164          * Constructs a QName from a node's value.
165          *
166          * @param domNode the DOM node with a QName value
167          * @return a QName from a node's value, or null if the given node has no value
168          */
169         static QName* getNodeValueAsQName(const xercesc::DOMNode* domNode);
170
171         /**
172          * Returns a boolean based on a node's value.
173          *
174          * @param domNode   the DOM node with a boolean (1/0/true/false) value
175          * @param def       value to return if the node is null/missing
176          * @return a bool value based on the node's value, or a default value
177          */
178         static bool getNodeValueAsBool(const xercesc::DOMNode* domNode, bool def);
179
180         /**
181          * Appends the child Element to the parent Element,
182          * importing the child Element into the parent's Document if needed.
183          *
184          * @param parentElement the parent Element
185          * @param childElement the child Element
186          * @return the child Element that was added (may be an imported copy)
187          */
188         static xercesc::DOMElement* appendChildElement(xercesc::DOMElement* parentElement, xercesc::DOMElement* childElement);
189
190         /**
191          * Checks the qualified name of a node.
192          *
193          * @param n     node to check
194          * @param ns    namespace to compare with
195          * @param local local name to compare with
196          * @return  true iff the node's qualified name matches the other parameters
197          */
198         static bool isNodeNamed(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* local);
199
200         /**
201          * Returns the first matching child element of the node if any.
202          *
203          * @param n         node to check
204          * @param localName local name to compare with or nullptr for any match
205          * @return  the first matching child node of type Element, or nullptr
206          */
207         static xercesc::DOMElement* getFirstChildElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
208
209         /**
210          * Returns the last matching child element of the node if any.
211          *
212          * @param n     node to check
213          * @param localName local name to compare with or nullptr for any match
214          * @return  the last matching child node of type Element, or nullptr
215          */
216         static xercesc::DOMElement* getLastChildElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
217
218         /**
219          * Returns the next matching sibling element of the node if any.
220          *
221          * @param n     node to check
222          * @param localName local name to compare with or nullptr for any match
223          * @return  the next matching sibling node of type Element, or nullptr
224          */
225         static xercesc::DOMElement* getNextSiblingElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
226
227         /**
228          * Returns the previous matching sibling element of the node if any.
229          *
230          * @param n     node to check
231          * @param localName local name to compare with or nullptr for any match
232          * @return  the previous matching sibling node of type Element, or nullptr
233          */
234         static xercesc::DOMElement* getPreviousSiblingElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
235
236         /**
237          * Returns the first matching child element of the node if any.
238          *
239          * @param n         node to check
240          * @param ns        namespace to compare with
241          * @param localName local name to compare with
242          * @return  the first matching child node of type Element, or nullptr
243          */
244         static xercesc::DOMElement* getFirstChildElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
245
246         /**
247          * Returns the last matching child element of the node if any.
248          *
249          * @param n         node to check
250          * @param ns        namespace to compare with
251          * @param localName local name to compare with
252          * @return  the last matching child node of type Element, or nullptr
253          */
254         static xercesc::DOMElement* getLastChildElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
255
256         /**
257          * Returns the next matching sibling element of the node if any.
258          *
259          * @param n         node to check
260          * @param ns        namespace to compare with
261          * @param localName local name to compare with
262          * @return  the next matching sibling node of type Element, or nullptr
263          */
264         static xercesc::DOMElement* getNextSiblingElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
265
266         /**
267          * Returns the previous matching sibling element of the node if any.
268          *
269          * @param n         node to check
270          * @param ns        namespace to compare with
271          * @param localName local name to compare with
272          * @return  the previous matching sibling node of type Element, or nullptr
273          */
274         static xercesc::DOMElement* getPreviousSiblingElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
275
276         /**
277          * Returns the content of the first Text node found in the element, if any.
278          * This is roughly similar to the DOM getTextContent function, but only
279          * examines the immediate children of the element.
280          *
281          * @param e     element to examine
282          * @return the content of the first Text node found, or nullptr
283          */
284         static const XMLCh* getTextContent(const xercesc::DOMElement* e);
285
286         /**
287          * Returns the content of the specified attribute node as a string,
288          * or the default value, if the attribute is not present.
289          *
290          * @param e         element to examine (may be nullptr)
291          * @param defValue  default value to return
292          * @param localName local name of attribute
293          * @param ns        namespace of attribute
294          * @return  the specified attribute's value, or the specified default
295          */
296         static std::string getAttrString(
297             const xercesc::DOMElement* e, const char* defValue, const XMLCh* localName, const XMLCh* ns=nullptr
298             );
299
300         /**
301          * Returns the content of the specified attribute node as an integer,
302          * or the default value, if the attribute is not present.
303          *
304          * @param e         element to examine (may be nullptr)
305          * @param defValue  default value to return
306          * @param localName local name of attribute
307          * @param ns        namespace of attribute
308          * @return  the specified attribute's value, or the specified default
309          */
310         static int getAttrInt(
311             const xercesc::DOMElement* e, int defValue, const XMLCh* localName, const XMLCh* ns=nullptr
312             );
313
314         /**
315          * Returns the content of the specified attribute node as a boolean,
316          * or the default value, if the attribute is not present.
317          *
318          * @param e         element to examine (may be nullptr)
319          * @param defValue  default value to return
320          * @param localName local name of attribute
321          * @param ns        namespace of attribute
322          * @return  the specified attribute's value, or the specified default
323          */
324         static bool getAttrBool(
325             const xercesc::DOMElement* e, bool defValue, const XMLCh* localName, const XMLCh* ns=nullptr
326             );
327
328         /**
329          * Serializes the DOM node provided into a buffer using UTF-8 encoding and
330          * the default XML serializer available. No manipulation or formatting is applied.
331          *
332          * @param n         node to serialize
333          * @param buf       buffer to serialize element into
334          * @param pretty    enable pretty printing if supported
335          */
336         static void serialize(const xercesc::DOMNode* n, std::string& buf, bool pretty=false);
337
338         /**
339          * Serializes the DOM node provided to a stream using UTF-8 encoding and
340          * the default XML serializer available. No manipulation or formatting is applied.
341          *
342          * @param n         node to serialize
343          * @param out       stream to serialize element into
344          * @param pretty    enable pretty printing if supported
345          * @return reference to output stream
346          */
347         static std::ostream& serialize(const xercesc::DOMNode* n, std::ostream& out, bool pretty=false);
348     };
349
350     /**
351      * Serializes the DOM node provided to a stream using UTF-8 encoding and
352      * the default XML serializer available. No manipulation or formatting is applied.
353      *
354      * @param n      node to serialize
355      * @param ostr   stream to serialize element into
356      * @return reference to output stream
357      */
358     extern XMLTOOL_API std::ostream& operator<<(std::ostream& ostr, const xercesc::DOMNode& n);
359
360     /**
361      * Marshalls and serializes the XMLObject provided to a stream using UTF-8 encoding and
362      * the default XML serializer available. No manipulation or formatting is applied.
363      *
364      * <p>The marshaller operation takes no parameters.
365      *
366      * @param obj    object to serialize
367      * @param ostr   stream to serialize object into
368      * @return reference to output stream
369      */
370     extern XMLTOOL_API std::ostream& operator<<(std::ostream& ostr, const XMLObject& obj);
371 };
372
373 #endif /* __xmltooling_xmlhelper_h__ */