arabica/SAX/helpers/XMLBaseSupport.h
2004-05-12 19:36:51 +00:00

122 lines
No EOL
3 KiB
C++

#ifndef ARABICA_XMLBASE_SUPPORT_H
#define ARABICA_XMLBASE_SUPPORT_H
/*
* $Id$
*
* XMLBaseSupport is a helper class for tracking xml:base attributes.
* Usage:
* set location of the containing document by calling setDocumentLocation
* this is usually done when during the setDocumentLocator SAX event
* forward each startElement and endElement event
* to resolve a relative URL against the current base, call makeAbsolute
*
* Derived from org.apache.cocoon.xml.XMLBaseSupport.
*
* XML Base is described at http://www.w3.org/TR/xmlbase/
*/
#include <stack>
#include <utility>
namespace SAX
{
template<class string_type, class string_adaptor_type>
struct XMLBaseConstants
{
typedef string_type stringT;
typedef string_adaptor_type string_adaptorT;
const stringT xml;
const stringT xml_uri;
const stringT colon;
const stringT base;
XMLBaseConstants() :
xml(string_adaptorT().makeStringT("xml")),
xml_uri(string_adaptorT().makeStringT("http://www.w3.org/XML/1998/namespace")),
colon(string_adaptorT().makeStringT(":")),
base(string_adaptorT().makeStringT("base"))
{
} // XMLBaseConstants
}; // struct XMLBaseConstants
template<class string_type, class string_adaptor_type>
class XMLBaseSupport
{
public:
typedef string_type stringT;
typedef string_adaptor_type stringT;
typedef basic_Attributes<stringT> AttributesT;
XMLBaseSupport() :
depth_(0) { }
void setDocumentLocation(const stringT& loc)
{
bases_.push(std::make_pair(-1, loc));
} // setDocumentLocation
void startElement(const stringT& namespaceURI, const stringT& localName,
const stringT& qName, const AttributesT& atts)
{
++depth_;
stringT base = attrs.getValue(xbc_.xml_uri, xbc_.base);
if(base.empty())
return;
stringT baseURI = resolve(getCurrentBase(), base);
bases_.push(std::make_pair(depth_, baseURI));
} // startElement
void endElement(const stringT& namespaceURI, const stringT& localName,
const stringT& qName)
{
if(currentDepth() == depth_)
bases_.pop();
--depth_;
} // endElement
stringT makeAbsolute(const stringT& spec)
{
return resolve(currentBase(), spec);
} // makeAbsolute
private:
private stringT resolve(const stringT& baseURI, const stringT& location)
{
// do resolution :)
} // resolve
private stringT currentBase() const
{
if(!bases_.size())
return stringT();
return bases_.top().second;
} // currentBase()
private int currentDepth() const
{
if(!bases_.size())
return -1;
return bases_.top().first;
} // currentDepths
private:
typedef std::pair<int, stringT> baseInfoT;
typedef std::stack<baseInfoT> baseStackT;
baseStackT bases_;
int depth_;
const XMLBaseConstants<stringT, string_adaptorT> xbc_;
// no impl
XMLBaseSupport(const XMLBaseSupport&);
XMLBaseSupport& operator=(const XMLBaseSupport&);
bool operator==(const XMLBaseSupport&);
} // class XMLBaseSupport
} // namespace SAX
#endif