Credential resolver plugin
[shibboleth/cpp-xmltooling.git] / xmltooling / util / XMLHelper.cpp
1 /*\r
2  *  Copyright 2001-2006 Internet2\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *     http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 /**\r
18  * XMLHelper.cpp\r
19  * \r
20  * A helper class for working with W3C DOM objects. \r
21  */\r
22 \r
23 #include "internal.h"\r
24 #include "exceptions.h"\r
25 #include "util/XMLHelper.h"\r
26 #include "util/XMLConstants.h"\r
27 \r
28 #include <xercesc/framework/MemBufFormatTarget.hpp>\r
29 #include <xercesc/util/XMLUniDefs.hpp>\r
30 \r
31 using namespace xmltooling;\r
32 \r
33 static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull };\r
34     \r
35 bool XMLHelper::hasXSIType(const DOMElement* e)\r
36 {\r
37     if (e) {\r
38         if (e->hasAttributeNS(XMLConstants::XSI_NS, type)) {\r
39             return true;\r
40         }\r
41     }\r
42 \r
43     return false;\r
44 }\r
45 \r
46 QName* XMLHelper::getXSIType(const DOMElement* e)\r
47 {\r
48     DOMAttr* attribute = e->getAttributeNodeNS(XMLConstants::XSI_NS, type);\r
49     if (attribute) {\r
50         const XMLCh* attributeValue = attribute->getTextContent();\r
51         if (attributeValue && *attributeValue) {\r
52             int i;\r
53             if ((i=XMLString::indexOf(attributeValue,chColon))>0) {\r
54                 XMLCh* prefix=new XMLCh[i+1];\r
55                 XMLString::subString(prefix,attributeValue,0,i);\r
56                 prefix[i]=chNull;\r
57                 QName* ret=new QName(e->lookupNamespaceURI(prefix), attributeValue + i + 1, prefix);\r
58                 delete[] prefix;\r
59                 return ret;\r
60             }\r
61             else {\r
62                 return new QName(e->lookupNamespaceURI(&chNull), attributeValue);\r
63             }\r
64         }\r
65     }\r
66 \r
67     return NULL;\r
68 }\r
69 \r
70 DOMAttr* XMLHelper::getIdAttribute(const DOMElement* domElement)\r
71 {\r
72     if(!domElement->hasAttributes()) {\r
73         return NULL;\r
74     }\r
75     \r
76     DOMNamedNodeMap* attributes = domElement->getAttributes();\r
77     DOMAttr* attribute;\r
78     for(XMLSize_t i = 0; i < attributes->getLength(); i++) {\r
79         attribute = static_cast<DOMAttr*>(attributes->item(i));\r
80         if(attribute->isId()) {\r
81             return attribute;\r
82         }\r
83     }\r
84     \r
85     return NULL;\r
86 }\r
87 \r
88 QName* XMLHelper::getNodeQName(const DOMNode* domNode)\r
89 {\r
90     if (domNode)\r
91         return new QName(domNode->getNamespaceURI(), domNode->getLocalName(), domNode->getPrefix());\r
92     return NULL; \r
93 }\r
94 \r
95 QName* XMLHelper::getAttributeValueAsQName(const DOMAttr* attribute)\r
96 {\r
97     if (!attribute)\r
98         return NULL;\r
99     \r
100     int i;\r
101     const XMLCh* attributeValue=attribute->getTextContent();\r
102     if (attributeValue && (i=XMLString::indexOf(attributeValue,chColon))>0) {\r
103         XMLCh* prefix=new XMLCh[i+1];\r
104         XMLString::subString(prefix,attributeValue,0,i);\r
105         prefix[i]=chNull;\r
106         QName* ret=new QName(attribute->lookupNamespaceURI(prefix), attributeValue + i + 1, prefix);\r
107         delete[] prefix;\r
108         return ret;\r
109     }\r
110     \r
111     return new QName(attribute->lookupNamespaceURI(NULL), attributeValue);\r
112 }\r
113 \r
114 DOMElement* XMLHelper::appendChildElement(DOMElement* parentElement, DOMElement* childElement)\r
115 {\r
116     DOMDocument* parentDocument = parentElement->getOwnerDocument();\r
117     if (childElement->getOwnerDocument() != parentDocument) {\r
118         childElement = static_cast<DOMElement*>(parentDocument->importNode(childElement, true));\r
119     }\r
120 \r
121     parentElement->appendChild(childElement);\r
122     return childElement;\r
123 }\r
124 \r
125 const XMLCh* XMLHelper::getTextContent(const DOMElement* e)\r
126 {\r
127     DOMNode* child=e->getFirstChild();\r
128     while (child) {\r
129         if (child->getNodeType()==DOMNode::TEXT_NODE)\r
130             return child->getNodeValue();\r
131         child=child->getNextSibling();\r
132     }\r
133     return NULL;\r
134 }\r
135 \r
136 DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* localName)\r
137 {\r
138     DOMNode* child = n->getFirstChild();\r
139     while (child && child->getNodeType() != DOMNode::ELEMENT_NODE)\r
140         child = child->getNextSibling();\r
141     if (child && localName) {\r
142         if (!XMLString::equals(localName,child->getLocalName()))\r
143             return getNextSiblingElement(child, localName);\r
144     }\r
145     return static_cast<DOMElement*>(child);\r
146 }    \r
147 \r
148 DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* localName)\r
149 {\r
150     DOMNode* child = n->getLastChild();\r
151     while (child && child->getNodeType() != DOMNode::ELEMENT_NODE)\r
152         child = child->getPreviousSibling();\r
153     if (child && localName) {\r
154         if (!XMLString::equals(localName,child->getLocalName()))\r
155             return getPreviousSiblingElement(child, localName);\r
156     }\r
157     return static_cast<DOMElement*>(child);\r
158 }    \r
159 \r
160 DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)\r
161 {\r
162     DOMElement* e = getFirstChildElement(n, localName);\r
163     while (e && !XMLString::equals(e->getNamespaceURI(),ns))\r
164         e = getNextSiblingElement(e, localName);\r
165     return e;\r
166 }\r
167 \r
168 DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)\r
169 {\r
170     DOMElement* e = getLastChildElement(n, localName);\r
171     while (e && !XMLString::equals(e->getNamespaceURI(),ns))\r
172         e = getPreviousSiblingElement(e, localName);\r
173     return e;\r
174 }\r
175 \r
176 DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* localName)\r
177 {\r
178     DOMNode* sib = n->getNextSibling();\r
179     while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE)\r
180         sib = sib->getNextSibling();\r
181     if (sib && localName) {\r
182         if (!XMLString::equals(localName,sib->getLocalName()))\r
183             return getNextSiblingElement(sib, localName);\r
184     }   \r
185     return static_cast<DOMElement*>(sib);\r
186 }\r
187 \r
188 DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* localName)\r
189 {\r
190     DOMNode* sib = n->getPreviousSibling();\r
191     while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE)\r
192         sib = sib->getPreviousSibling();\r
193     if (sib && localName) {\r
194         if (!XMLString::equals(localName,sib->getLocalName()))\r
195             return getPreviousSiblingElement(sib, localName);\r
196     }   \r
197     return static_cast<DOMElement*>(sib);\r
198 }\r
199 \r
200 DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)\r
201 {\r
202     DOMElement* e = getNextSiblingElement(n, localName);\r
203     while (e && !XMLString::equals(e->getNamespaceURI(),ns))\r
204         e = getNextSiblingElement(e, localName);\r
205     return e;\r
206 }\r
207 \r
208 DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)\r
209 {\r
210     DOMElement* e = getPreviousSiblingElement(n, localName);\r
211     while (e && !XMLString::equals(e->getNamespaceURI(),ns))\r
212         e = getPreviousSiblingElement(e, localName);\r
213     return e;\r
214 }\r
215 \r
216 void XMLHelper::serialize(const DOMElement* e, std::string& buf)\r
217 {\r
218     static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull };\r
219     static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull };\r
220     DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype);\r
221     DOMWriter* serializer=(static_cast<DOMImplementationLS*>(impl))->createDOMWriter();\r
222     XercesJanitor<DOMWriter> janitor(serializer);\r
223     serializer->setEncoding(UTF8);\r
224     MemBufFormatTarget target;\r
225     if (!serializer->writeNode(&target,*e))\r
226         throw XMLParserException("unable to serialize XML");\r
227     buf.erase();\r
228     buf.append(reinterpret_cast<const char*>(target.getRawBuffer()),target.getLen());\r
229 }\r