2 * Copyright 2001-2009 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * A helper class for working with W3C DOM objects.
24 #include "exceptions.h"
26 #include "XMLObject.h"
27 #include "util/XMLHelper.h"
28 #include "util/XMLConstants.h"
30 #include <xercesc/framework/MemBufFormatTarget.hpp>
31 #include <xercesc/util/XMLUniDefs.hpp>
33 using namespace xmltooling;
34 using namespace xercesc;
37 static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull };
39 bool XMLHelper::hasXSIType(const DOMElement* e)
42 if (e->hasAttributeNS(xmlconstants::XSI_NS, type)) {
50 xmltooling::QName* XMLHelper::getXSIType(const DOMElement* e)
52 DOMAttr* attribute = e->getAttributeNodeNS(xmlconstants::XSI_NS, type);
54 const XMLCh* attributeValue = attribute->getTextContent();
55 if (attributeValue && *attributeValue) {
57 if ((i=XMLString::indexOf(attributeValue,chColon))>0) {
58 XMLCh* prefix=new XMLCh[i+1];
59 XMLString::subString(prefix,attributeValue,0,i);
61 xmltooling::QName* ret=new xmltooling::QName(e->lookupNamespaceURI(prefix), attributeValue + i + 1, prefix);
66 return new xmltooling::QName(e->lookupNamespaceURI(NULL), attributeValue);
74 DOMAttr* XMLHelper::getIdAttribute(const DOMElement* domElement)
76 if(!domElement->hasAttributes()) {
80 DOMNamedNodeMap* attributes = domElement->getAttributes();
82 for(XMLSize_t i = 0; i < attributes->getLength(); i++) {
83 attribute = static_cast<DOMAttr*>(attributes->item(i));
84 if(attribute->isId()) {
92 const XMLObject* XMLHelper::getXMLObjectById(const XMLObject& tree, const XMLCh* id)
94 if (XMLString::equals(id, tree.getXMLID()))
98 const list<XMLObject*>& children = tree.getOrderedChildren();
99 for (list<XMLObject*>::const_iterator i=children.begin(); i!=children.end(); ++i) {
101 ret = getXMLObjectById(*(*i), id);
110 XMLObject* XMLHelper::getXMLObjectById(XMLObject& tree, const XMLCh* id)
112 if (XMLString::equals(id, tree.getXMLID()))
116 const list<XMLObject*>& children = tree.getOrderedChildren();
117 for (list<XMLObject*>::const_iterator i=children.begin(); i!=children.end(); ++i) {
119 ret = getXMLObjectById(*(*i), id);
128 xmltooling::QName* XMLHelper::getNodeQName(const DOMNode* domNode)
131 return new xmltooling::QName(domNode->getNamespaceURI(), domNode->getLocalName(), domNode->getPrefix());
135 xmltooling::QName* XMLHelper::getAttributeValueAsQName(const DOMAttr* attribute)
137 return getNodeValueAsQName(attribute);
140 xmltooling::QName* XMLHelper::getNodeValueAsQName(const DOMNode* domNode)
146 const XMLCh* value=domNode->getTextContent();
147 if (value && (i=XMLString::indexOf(value,chColon))>0) {
148 XMLCh* prefix=new XMLCh[i+1];
149 XMLString::subString(prefix,value,0,i);
151 xmltooling::QName* ret=new xmltooling::QName(domNode->lookupNamespaceURI(prefix), value + i + 1, prefix);
156 return new xmltooling::QName(domNode->lookupNamespaceURI(NULL), value);
159 DOMElement* XMLHelper::appendChildElement(DOMElement* parentElement, DOMElement* childElement)
161 DOMDocument* parentDocument = parentElement->getOwnerDocument();
162 if (childElement->getOwnerDocument() != parentDocument) {
163 childElement = static_cast<DOMElement*>(parentDocument->importNode(childElement, true));
166 parentElement->appendChild(childElement);
170 bool XMLHelper::isNodeNamed(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* local)
172 return (n && XMLString::equals(local,n->getLocalName()) && XMLString::equals(ns,n->getNamespaceURI()));
175 const XMLCh* XMLHelper::getTextContent(const DOMElement* e)
177 DOMNode* child=e->getFirstChild();
179 if (child->getNodeType()==DOMNode::TEXT_NODE)
180 return child->getNodeValue();
181 child=child->getNextSibling();
186 DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* localName)
188 DOMNode* child = n->getFirstChild();
189 while (child && child->getNodeType() != DOMNode::ELEMENT_NODE)
190 child = child->getNextSibling();
191 if (child && localName) {
192 if (!XMLString::equals(localName,child->getLocalName()))
193 return getNextSiblingElement(child, localName);
195 return static_cast<DOMElement*>(child);
198 DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* localName)
200 DOMNode* child = n->getLastChild();
201 while (child && child->getNodeType() != DOMNode::ELEMENT_NODE)
202 child = child->getPreviousSibling();
203 if (child && localName) {
204 if (!XMLString::equals(localName,child->getLocalName()))
205 return getPreviousSiblingElement(child, localName);
207 return static_cast<DOMElement*>(child);
210 DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)
212 DOMElement* e = getFirstChildElement(n, localName);
213 while (e && !XMLString::equals(e->getNamespaceURI(),ns))
214 e = getNextSiblingElement(e, localName);
218 DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)
220 DOMElement* e = getLastChildElement(n, localName);
221 while (e && !XMLString::equals(e->getNamespaceURI(),ns))
222 e = getPreviousSiblingElement(e, localName);
226 DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* localName)
228 DOMNode* sib = n->getNextSibling();
229 while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE)
230 sib = sib->getNextSibling();
231 if (sib && localName) {
232 if (!XMLString::equals(localName,sib->getLocalName()))
233 return getNextSiblingElement(sib, localName);
235 return static_cast<DOMElement*>(sib);
238 DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* localName)
240 DOMNode* sib = n->getPreviousSibling();
241 while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE)
242 sib = sib->getPreviousSibling();
243 if (sib && localName) {
244 if (!XMLString::equals(localName,sib->getLocalName()))
245 return getPreviousSiblingElement(sib, localName);
247 return static_cast<DOMElement*>(sib);
250 DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)
252 DOMElement* e = getNextSiblingElement(n, localName);
253 while (e && !XMLString::equals(e->getNamespaceURI(),ns))
254 e = getNextSiblingElement(e, localName);
258 DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName)
260 DOMElement* e = getPreviousSiblingElement(n, localName);
261 while (e && !XMLString::equals(e->getNamespaceURI(),ns))
262 e = getPreviousSiblingElement(e, localName);
266 void XMLHelper::serialize(const DOMNode* n, std::string& buf, bool pretty)
268 static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull };
269 static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, chNull };
271 MemBufFormatTarget target;
272 DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype);
274 #ifdef XMLTOOLING_XERCESC_COMPLIANT_DOMLS
275 DOMLSSerializer* serializer = static_cast<DOMImplementationLS*>(impl)->createLSSerializer();
276 XercesJanitor<DOMLSSerializer> janitor(serializer);
277 if (pretty && serializer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty))
278 serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty);
279 DOMLSOutput *theOutput = static_cast<DOMImplementationLS*>(impl)->createLSOutput();
280 XercesJanitor<DOMLSOutput> j_theOutput(theOutput);
281 theOutput->setEncoding(UTF8);
282 theOutput->setByteStream(&target);
283 if (!serializer->write(n, theOutput))
284 throw XMLParserException("unable to serialize XML");
286 DOMWriter* serializer = static_cast<DOMImplementationLS*>(impl)->createDOMWriter();
287 XercesJanitor<DOMWriter> janitor(serializer);
288 serializer->setEncoding(UTF8);
289 if (pretty && serializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, pretty))
290 serializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, pretty);
291 if (!serializer->writeNode(&target, *n))
292 throw XMLParserException("unable to serialize XML");
296 buf.append(reinterpret_cast<const char*>(target.getRawBuffer()),target.getLen());
300 class StreamFormatTarget : public XMLFormatTarget
303 StreamFormatTarget(std::ostream& out) : m_out(out) {}
304 ~StreamFormatTarget() {}
306 void writeChars(const XMLByte *const toWrite, const xsecsize_t count, XMLFormatter *const formatter) {
307 m_out.write(reinterpret_cast<const char*>(toWrite),count);
319 ostream& XMLHelper::serialize(const DOMNode* n, ostream& out, bool pretty)
321 static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull };
322 static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, chNull };
324 StreamFormatTarget target(out);
325 DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype);
327 #ifdef XMLTOOLING_XERCESC_COMPLIANT_DOMLS
328 DOMLSSerializer* serializer = static_cast<DOMImplementationLS*>(impl)->createLSSerializer();
329 XercesJanitor<DOMLSSerializer> janitor(serializer);
330 if (pretty && serializer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty))
331 serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty);
332 DOMLSOutput *theOutput = static_cast<DOMImplementationLS*>(impl)->createLSOutput();
333 XercesJanitor<DOMLSOutput> j_theOutput(theOutput);
334 theOutput->setEncoding(UTF8);
335 theOutput->setByteStream(&target);
336 if (!serializer->write(n, theOutput))
337 throw XMLParserException("unable to serialize XML");
339 DOMWriter* serializer=(static_cast<DOMImplementationLS*>(impl))->createDOMWriter();
340 XercesJanitor<DOMWriter> janitor(serializer);
341 serializer->setEncoding(UTF8);
342 if (pretty && serializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, pretty))
343 serializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, pretty);
344 if (!serializer->writeNode(&target,*n))
345 throw XMLParserException("unable to serialize XML");
351 ostream& xmltooling::operator<<(ostream& ostr, const DOMNode& node)
353 return XMLHelper::serialize(&node, ostr);
356 ostream& xmltooling::operator<<(ostream& ostr, const XMLObject& obj)
358 return ostr << *(obj.marshall());