X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-xmltooling.git;a=blobdiff_plain;f=xmltooling%2Futil%2FXMLHelper.cpp;h=26823958c5d9d4dce3fb3583828f4ba52f3162fd;hp=6128bff61f6dd9a97883f9ca1433be0c85c6cc5d;hb=2d795c731e6729309044607154978696a87fd900;hpb=c8954c4805d6fab88944447597055ea4496a0fdf diff --git a/xmltooling/util/XMLHelper.cpp b/xmltooling/util/XMLHelper.cpp index 6128bff..2682395 100644 --- a/xmltooling/util/XMLHelper.cpp +++ b/xmltooling/util/XMLHelper.cpp @@ -1,17 +1,21 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. * - * http://www.apache.org/licenses/LICENSE-2.0 + * UCAID licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the + * License at * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. */ /** @@ -22,27 +26,28 @@ #include "internal.h" #include "exceptions.h" +#include "QName.h" +#include "XMLObject.h" #include "util/XMLHelper.h" #include "util/XMLConstants.h" +#include +#include +#include #include #include using namespace xmltooling; using namespace xercesc; +using namespace boost::lambda; +using namespace boost; using namespace std; static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull }; bool XMLHelper::hasXSIType(const DOMElement* e) { - if (e) { - if (e->hasAttributeNS(xmlconstants::XSI_NS, type)) { - return true; - } - } - - return false; + return (e && e->hasAttributeNS(xmlconstants::XSI_NS, type)); } xmltooling::QName* XMLHelper::getXSIType(const DOMElement* e) @@ -61,30 +66,30 @@ xmltooling::QName* XMLHelper::getXSIType(const DOMElement* e) return ret; } else { - return new xmltooling::QName(e->lookupNamespaceURI(NULL), attributeValue); + return new xmltooling::QName(e->lookupNamespaceURI(nullptr), attributeValue); } } } - return NULL; + return nullptr; } DOMAttr* XMLHelper::getIdAttribute(const DOMElement* domElement) { if(!domElement->hasAttributes()) { - return NULL; + return nullptr; } DOMNamedNodeMap* attributes = domElement->getAttributes(); DOMAttr* attribute; - for(XMLSize_t i = 0; i < attributes->getLength(); i++) { + for(XMLSize_t i = 0; i < attributes->getLength(); ++i) { attribute = static_cast(attributes->item(i)); if(attribute->isId()) { return attribute; } } - return NULL; + return nullptr; } const XMLObject* XMLHelper::getXMLObjectById(const XMLObject& tree, const XMLCh* id) @@ -94,7 +99,7 @@ const XMLObject* XMLHelper::getXMLObjectById(const XMLObject& tree, const XMLCh* const XMLObject* ret; const list& children = tree.getOrderedChildren(); - for (list::const_iterator i=children.begin(); i!=children.end(); ++i) { + for (list::const_iterator i = children.begin(); i != children.end(); ++i) { if (*i) { ret = getXMLObjectById(*(*i), id); if (ret) @@ -102,17 +107,17 @@ const XMLObject* XMLHelper::getXMLObjectById(const XMLObject& tree, const XMLCh* } } - return NULL; + return nullptr; } XMLObject* XMLHelper::getXMLObjectById(XMLObject& tree, const XMLCh* id) { if (XMLString::equals(id, tree.getXMLID())) return &tree; - + XMLObject* ret; const list& children = tree.getOrderedChildren(); - for (list::const_iterator i=children.begin(); i!=children.end(); ++i) { + for (list::const_iterator i = children.begin(); i != children.end(); ++i) { if (*i) { ret = getXMLObjectById(*(*i), id); if (ret) @@ -120,14 +125,54 @@ XMLObject* XMLHelper::getXMLObjectById(XMLObject& tree, const XMLCh* id) } } - return NULL; + return nullptr; +} + +void XMLHelper::getNonVisiblyUsedPrefixes(const XMLObject& tree, map& prefixes) +{ + map child_prefixes; + for(list::const_iterator i = tree.getOrderedChildren().begin(); i != tree.getOrderedChildren().end(); ++i) { + if (*i) { + getNonVisiblyUsedPrefixes(*(*i), child_prefixes); + } + } + const set& nsset = tree.getNamespaces(); + for (set::const_iterator ns = nsset.begin(); ns != nsset.end(); ++ns) { + // Check for xmlns:xml. + if (XMLString::equals(ns->getNamespacePrefix(), xmlconstants::XML_PREFIX) && XMLString::equals(ns->getNamespaceURI(), xmlconstants::XML_NS)) + continue; + switch (ns->usage()) { + case Namespace::Indeterminate: + break; + case Namespace::VisiblyUsed: + { + // See if the prefix was noted as non-visible below. + const XMLCh* p = ns->getNamespacePrefix() ? ns->getNamespacePrefix() : &chNull; + map::iterator decl = child_prefixes.find(p); + if (decl != child_prefixes.end()) { + // It's declared below, see if it's the same namespace. If so, pull it from the set, + // otherwise leave it in the set. + if (decl->second == (ns->getNamespaceURI() ? ns->getNamespaceURI() : &chNull)) + child_prefixes.erase(decl); + } + break; + } + case Namespace::NonVisiblyUsed: + // It may already be in the map from another branch of the tree, but as long + // as it's set to something so the parent knows about it, we're good. + prefixes[ns->getNamespacePrefix() ? ns->getNamespacePrefix() : &chNull] = (ns->getNamespaceURI() ? ns->getNamespaceURI() : &chNull); + break; + } + } + + prefixes.insert(child_prefixes.begin(), child_prefixes.end()); } xmltooling::QName* XMLHelper::getNodeQName(const DOMNode* domNode) { if (domNode) return new xmltooling::QName(domNode->getNamespaceURI(), domNode->getLocalName(), domNode->getPrefix()); - return NULL; + return nullptr; } xmltooling::QName* XMLHelper::getAttributeValueAsQName(const DOMAttr* attribute) @@ -138,11 +183,14 @@ xmltooling::QName* XMLHelper::getAttributeValueAsQName(const DOMAttr* attribute) xmltooling::QName* XMLHelper::getNodeValueAsQName(const DOMNode* domNode) { if (!domNode) - return NULL; + return nullptr; - int i; const XMLCh* value=domNode->getTextContent(); - if (value && (i=XMLString::indexOf(value,chColon))>0) { + if (!value || !*value) + return nullptr; + + int i; + if ((i=XMLString::indexOf(value,chColon))>0) { XMLCh* prefix=new XMLCh[i+1]; XMLString::subString(prefix,value,0,i); prefix[i]=chNull; @@ -151,7 +199,21 @@ xmltooling::QName* XMLHelper::getNodeValueAsQName(const DOMNode* domNode) return ret; } - return new xmltooling::QName(domNode->lookupNamespaceURI(NULL), value); + return new xmltooling::QName(domNode->lookupNamespaceURI(nullptr), value); +} + +bool XMLHelper::getNodeValueAsBool(const xercesc::DOMNode* domNode, bool def) +{ + if (!domNode) + return def; + const XMLCh* value = domNode->getNodeValue(); + if (!value || !*value) + return def; + if (*value == chLatin_t || *value == chDigit_1) + return true; + else if (*value == chLatin_f || *value == chDigit_0) + return false; + return def; } DOMElement* XMLHelper::appendChildElement(DOMElement* parentElement, DOMElement* childElement) @@ -165,20 +227,25 @@ DOMElement* XMLHelper::appendChildElement(DOMElement* parentElement, DOMElement* return childElement; } +bool XMLHelper::isNodeNamed(const xercesc::DOMNode* n, const XMLCh* ns, const XMLCh* local) +{ + return (n && XMLString::equals(local,n->getLocalName()) && XMLString::equals(ns,n->getNamespaceURI())); +} + const XMLCh* XMLHelper::getTextContent(const DOMElement* e) { - DOMNode* child=e->getFirstChild(); + DOMNode* child = e ? e->getFirstChild() : nullptr; while (child) { - if (child->getNodeType()==DOMNode::TEXT_NODE) + if (child->getNodeType() == DOMNode::TEXT_NODE) return child->getNodeValue(); - child=child->getNextSibling(); + child = child->getNextSibling(); } - return NULL; + return nullptr; } DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* localName) { - DOMNode* child = n->getFirstChild(); + DOMNode* child = n ? n->getFirstChild() : nullptr; while (child && child->getNodeType() != DOMNode::ELEMENT_NODE) child = child->getNextSibling(); if (child && localName) { @@ -190,7 +257,7 @@ DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* local DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* localName) { - DOMNode* child = n->getLastChild(); + DOMNode* child = n ? n->getLastChild() : nullptr; while (child && child->getNodeType() != DOMNode::ELEMENT_NODE) child = child->getPreviousSibling(); if (child && localName) { @@ -218,7 +285,7 @@ DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* ns, co DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* localName) { - DOMNode* sib = n->getNextSibling(); + DOMNode* sib = n ? n->getNextSibling() : nullptr; while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE) sib = sib->getNextSibling(); if (sib && localName) { @@ -230,7 +297,7 @@ DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* loca DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* localName) { - DOMNode* sib = n->getPreviousSibling(); + DOMNode* sib = n ? n->getPreviousSibling() : nullptr; while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE) sib = sib->getPreviousSibling(); if (sib && localName) { @@ -256,10 +323,49 @@ DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* return e; } +string XMLHelper::getAttrString(const DOMElement* e, const char* defValue, const XMLCh* localName, const XMLCh* ns) +{ + if (e) { + auto_ptr_char val(e->getAttributeNS(ns, localName)); + if (val.get() && *val.get()) + return val.get(); + } + return defValue ? defValue : ""; +} + +int XMLHelper::getAttrInt(const DOMElement* e, int defValue, const XMLCh* localName, const XMLCh* ns) +{ + if (e) { + const XMLCh* val = e->getAttributeNS(ns, localName); + if (val && *val) { + try { + return XMLString::parseInt(val); + } + catch (XMLException&) { + } + } + } + return defValue; +} + +bool XMLHelper::getAttrBool(const DOMElement* e, bool defValue, const XMLCh* localName, const XMLCh* ns) +{ + if (e) { + const XMLCh* val = e->getAttributeNS(ns, localName); + if (val) { + if (*val == chLatin_t || *val == chDigit_1) + return true; + if (*val == chLatin_f || *val == chDigit_0) + return false; + } + } + return defValue; +} + void XMLHelper::serialize(const DOMNode* n, std::string& buf, bool pretty) { static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull }; - static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull }; + static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, chNull }; MemBufFormatTarget target; DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype); @@ -269,9 +375,9 @@ void XMLHelper::serialize(const DOMNode* n, std::string& buf, bool pretty) XercesJanitor janitor(serializer); if (pretty && serializer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty)) serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty); - DOMLSOutput *theOutput = static_cast(impl)->createLSOutput(); - XercesJanitor j_theOutput(theOutput); - theOutput->setEncoding(UTF8); + DOMLSOutput *theOutput = static_cast(impl)->createLSOutput(); + XercesJanitor j_theOutput(theOutput); + theOutput->setEncoding(UTF8); theOutput->setByteStream(&target); if (!serializer->write(n, theOutput)) throw XMLParserException("unable to serialize XML"); @@ -312,7 +418,7 @@ namespace { ostream& XMLHelper::serialize(const DOMNode* n, ostream& out, bool pretty) { static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull }; - static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull }; + static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, chNull }; StreamFormatTarget target(out); DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype); @@ -322,9 +428,9 @@ ostream& XMLHelper::serialize(const DOMNode* n, ostream& out, bool pretty) XercesJanitor janitor(serializer); if (pretty && serializer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty)) serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, pretty); - DOMLSOutput *theOutput = static_cast(impl)->createLSOutput(); - XercesJanitor j_theOutput(theOutput); - theOutput->setEncoding(UTF8); + DOMLSOutput *theOutput = static_cast(impl)->createLSOutput(); + XercesJanitor j_theOutput(theOutput); + theOutput->setEncoding(UTF8); theOutput->setByteStream(&target); if (!serializer->write(n, theOutput)) throw XMLParserException("unable to serialize XML"); @@ -348,5 +454,11 @@ ostream& xmltooling::operator<<(ostream& ostr, const DOMNode& node) ostream& xmltooling::operator<<(ostream& ostr, const XMLObject& obj) { - return ostr << *(obj.marshall()); + try { + return ostr << *(obj.marshall()); + } + catch (DOMException& ex) { + auto_ptr_char msg(ex.getMessage()); + throw XMLParserException(msg.get()); + } }