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