Set fourth file version digit to signify rebuild.
[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          * <p>The caller is responsible for freeing the result.
108          *
109          * @param e the element
110          * @return the type or null
111          */
112         static QName* getXSIType(const xercesc::DOMElement* e);
113
114         /**
115          * Gets the ID attribute of a DOM element.
116          *
117          * @param domElement the DOM element
118          * @return the ID attribute or null if there isn't one
119          */
120         static xercesc::DOMAttr* getIdAttribute(const xercesc::DOMElement* domElement);
121
122         /**
123          * Attempts to locate an XMLObject from this point downward in the tree whose
124          * XML ID matches the supplied value.
125          *
126          * @param tree  root of tree to search
127          * @param id    ID value to locate
128          * @return XMLObject in the tree with a matching ID value, or nullptr
129          */
130         static const XMLObject* getXMLObjectById(const XMLObject& tree, const XMLCh* id);
131
132         /**
133          * Attempts to locate an XMLObject from this point downward in the tree whose
134          * XML ID matches the supplied value.
135          *
136          * @param tree  root of tree to search
137          * @param id    ID value to locate
138          * @return XMLObject in the tree with a matching ID value, or nullptr
139          */
140         static XMLObject* getXMLObjectById(XMLObject& tree, const XMLCh* id);
141
142         /**
143          * Returns the set of non-visibly-used namespace declarations found in a tree.
144          * <p>Each member of the set is a prefix/URI pair.
145          *
146          * @param tree      root of tree to search
147          * @param prefixes  container to store declarations
148          */
149         static void getNonVisiblyUsedPrefixes(const XMLObject& tree, std::map<xstring,xstring>& prefixes);
150
151         /**
152          * Gets the QName for the given DOM node.
153          *
154          * @param domNode the DOM node
155          * @return the QName for the element or null if the element was null
156          */
157         static QName* getNodeQName(const xercesc::DOMNode* domNode);
158
159         /**
160          * @deprecated
161          * Constructs a QName from an attribute's value.
162          * <p>The caller is responsible for freeing the result.
163          *
164          * @param attribute the attribute with a QName value
165          * @return a QName from an attribute's value, or null if the given attribute is null
166          */
167         static QName* getAttributeValueAsQName(const xercesc::DOMAttr* attribute);
168
169         /**
170          * Constructs a QName from a node's value.
171          * <p>The caller is responsible for freeing the result.
172          *
173          * @param domNode the DOM node with a QName value
174          * @return a QName from a node's value, or null if the given node has no value
175          */
176         static QName* getNodeValueAsQName(const xercesc::DOMNode* domNode);
177
178         /**
179          * Returns a boolean based on a node's value.
180          *
181          * @param domNode   the DOM node with a boolean (1/0/true/false) value
182          * @param def       value to return if the node is null/missing
183          * @return a bool value based on the node's value, or a default value
184          */
185         static bool getNodeValueAsBool(const xercesc::DOMNode* domNode, bool def);
186
187         /**
188          * Appends the child Element to the parent Element,
189          * importing the child Element into the parent's Document if needed.
190          *
191          * @param parentElement the parent Element
192          * @param childElement the child Element
193          * @return the child Element that was added (may be an imported copy)
194          */
195         static xercesc::DOMElement* appendChildElement(xercesc::DOMElement* parentElement, xercesc::DOMElement* childElement);
196
197         /**
198          * Checks the qualified name of a node.
199          *
200          * @param n     node to check
201          * @param ns    namespace to compare with
202          * @param local local name to compare with
203          * @return  true iff the node's qualified name matches the other parameters
204          */
205         static bool isNodeNamed(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* local);
206
207         /**
208          * Returns the first matching child element of the node if any.
209          *
210          * @param n         node to check
211          * @param localName local name to compare with or nullptr for any match
212          * @return  the first matching child node of type Element, or nullptr
213          */
214         static xercesc::DOMElement* getFirstChildElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
215
216         /**
217          * Returns the last matching child element of the node if any.
218          *
219          * @param n     node to check
220          * @param localName local name to compare with or nullptr for any match
221          * @return  the last matching child node of type Element, or nullptr
222          */
223         static xercesc::DOMElement* getLastChildElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
224
225         /**
226          * Returns the next matching sibling element of the node if any.
227          *
228          * @param n     node to check
229          * @param localName local name to compare with or nullptr for any match
230          * @return  the next matching sibling node of type Element, or nullptr
231          */
232         static xercesc::DOMElement* getNextSiblingElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
233
234         /**
235          * Returns the previous matching sibling element of the node if any.
236          *
237          * @param n     node to check
238          * @param localName local name to compare with or nullptr for any match
239          * @return  the previous matching sibling node of type Element, or nullptr
240          */
241         static xercesc::DOMElement* getPreviousSiblingElement(const xercesc::DOMNode* n, const XMLCh* localName=nullptr);
242
243         /**
244          * Returns the first matching child element of the node if any.
245          *
246          * @param n         node to check
247          * @param ns        namespace to compare with
248          * @param localName local name to compare with
249          * @return  the first matching child node of type Element, or nullptr
250          */
251         static xercesc::DOMElement* getFirstChildElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
252
253         /**
254          * Returns the last matching child element of the node if any.
255          *
256          * @param n         node to check
257          * @param ns        namespace to compare with
258          * @param localName local name to compare with
259          * @return  the last matching child node of type Element, or nullptr
260          */
261         static xercesc::DOMElement* getLastChildElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
262
263         /**
264          * Returns the next matching sibling element of the node if any.
265          *
266          * @param n         node to check
267          * @param ns        namespace to compare with
268          * @param localName local name to compare with
269          * @return  the next matching sibling node of type Element, or nullptr
270          */
271         static xercesc::DOMElement* getNextSiblingElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
272
273         /**
274          * Returns the previous matching sibling element of the node if any.
275          *
276          * @param n         node to check
277          * @param ns        namespace to compare with
278          * @param localName local name to compare with
279          * @return  the previous matching sibling node of type Element, or nullptr
280          */
281         static xercesc::DOMElement* getPreviousSiblingElement(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* localName);
282
283         /**
284          * Returns the content of the first Text node found in the element, if any.
285          * This is roughly similar to the DOM getTextContent function, but only
286          * examines the immediate children of the element.
287          *
288          * @param e     element to examine
289          * @return the content of the first Text node found, or nullptr
290          */
291         static const XMLCh* getTextContent(const xercesc::DOMElement* e);
292
293         /**
294          * Returns the content of the specified attribute node as a string,
295          * or the default value, if the attribute is not present.
296          *
297          * @param e         element to examine (may be nullptr)
298          * @param defValue  default value to return
299          * @param localName local name of attribute
300          * @param ns        namespace of attribute
301          * @return  the specified attribute's value, or the specified default
302          */
303         static std::string getAttrString(
304             const xercesc::DOMElement* e, const char* defValue, const XMLCh* localName, const XMLCh* ns=nullptr
305             );
306
307         /**
308          * Returns the content of the specified attribute node as an integer,
309          * or the default value, if the attribute is not present.
310          *
311          * @param e         element to examine (may be nullptr)
312          * @param defValue  default value to return
313          * @param localName local name of attribute
314          * @param ns        namespace of attribute
315          * @return  the specified attribute's value, or the specified default
316          */
317         static int getAttrInt(
318             const xercesc::DOMElement* e, int defValue, const XMLCh* localName, const XMLCh* ns=nullptr
319             );
320
321         /**
322          * Returns the content of the specified attribute node as a boolean,
323          * or the default value, if the attribute is not present.
324          *
325          * @param e         element to examine (may be nullptr)
326          * @param defValue  default value to return
327          * @param localName local name of attribute
328          * @param ns        namespace of attribute
329          * @return  the specified attribute's value, or the specified default
330          */
331         static bool getAttrBool(
332             const xercesc::DOMElement* e, bool defValue, const XMLCh* localName, const XMLCh* ns=nullptr
333             );
334
335         /**
336          * Serializes the DOM node provided into a buffer using UTF-8 encoding and
337          * the default XML serializer available. No manipulation or formatting is applied.
338          *
339          * @param n         node to serialize
340          * @param buf       buffer to serialize element into
341          * @param pretty    enable pretty printing if supported
342          */
343         static void serialize(const xercesc::DOMNode* n, std::string& buf, bool pretty=false);
344
345         /**
346          * Serializes the DOM node provided to a stream using UTF-8 encoding and
347          * the default XML serializer available. No manipulation or formatting is applied.
348          *
349          * @param n         node to serialize
350          * @param out       stream to serialize element into
351          * @param pretty    enable pretty printing if supported
352          * @return reference to output stream
353          */
354         static std::ostream& serialize(const xercesc::DOMNode* n, std::ostream& out, bool pretty=false);
355     };
356
357     /**
358      * Serializes the DOM node provided to a stream using UTF-8 encoding and
359      * the default XML serializer available. No manipulation or formatting is applied.
360      *
361      * @param n      node to serialize
362      * @param ostr   stream to serialize element into
363      * @return reference to output stream
364      */
365     extern XMLTOOL_API std::ostream& operator<<(std::ostream& ostr, const xercesc::DOMNode& n);
366
367     /**
368      * Marshalls and serializes the XMLObject provided to a stream using UTF-8 encoding and
369      * the default XML serializer available. No manipulation or formatting is applied.
370      *
371      * <p>The marshaller operation takes no parameters.
372      *
373      * @param obj    object to serialize
374      * @param ostr   stream to serialize object into
375      * @return reference to output stream
376      */
377     extern XMLTOOL_API std::ostream& operator<<(std::ostream& ostr, const XMLObject& obj);
378 };
379
380 #endif /* __xmltooling_xmlhelper_h__ */