2004-05-12 21:36:51 +02:00
|
|
|
#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>
|
2004-05-27 10:28:26 +02:00
|
|
|
#include <sstream>
|
2004-05-27 11:23:12 +02:00
|
|
|
#include <XML/UnicodeCharacters.h>
|
2004-05-12 21:36:51 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
template<class string_type, class string_adaptor_type = SAX::default_string_adaptor<string_type> >
|
|
|
|
class basic_XMLBaseSupport
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef string_type stringT;
|
2004-05-27 10:28:26 +02:00
|
|
|
typedef string_adaptor_type stringAdaptorT;
|
2004-05-27 11:23:12 +02:00
|
|
|
typedef typename string_adaptor_type::value_type valueT;
|
2004-05-12 21:36:51 +02:00
|
|
|
typedef basic_Attributes<stringT> AttributesT;
|
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
basic_XMLBaseSupport() :
|
|
|
|
depth_(0), SA_() { }
|
2004-05-12 21:36:51 +02:00
|
|
|
|
|
|
|
void setDocumentLocation(const stringT& loc)
|
|
|
|
{
|
|
|
|
bases_.push(std::make_pair(-1, loc));
|
|
|
|
} // setDocumentLocation
|
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
void startElement(const AttributesT& atts)
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
++depth_;
|
2004-05-27 11:23:12 +02:00
|
|
|
stringT base = atts.getValue(xbc_.xml_uri, xbc_.base);
|
2004-05-12 21:36:51 +02:00
|
|
|
if(base.empty())
|
|
|
|
return;
|
|
|
|
|
2004-06-28 23:22:29 +02:00
|
|
|
stringT baseURI = absolutiseAndTrim(currentBase(), base);
|
2004-05-12 21:36:51 +02:00
|
|
|
bases_.push(std::make_pair(depth_, baseURI));
|
|
|
|
} // startElement
|
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
void endElement()
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
if(currentDepth() == depth_)
|
|
|
|
bases_.pop();
|
|
|
|
--depth_;
|
|
|
|
} // endElement
|
|
|
|
|
|
|
|
stringT makeAbsolute(const stringT& spec)
|
|
|
|
{
|
2004-05-27 10:28:26 +02:00
|
|
|
return absolutise(currentBase(), spec);
|
2004-05-12 21:36:51 +02:00
|
|
|
} // makeAbsolute
|
|
|
|
|
|
|
|
private:
|
2004-05-27 11:23:12 +02:00
|
|
|
stringT absolutise(const stringT& baseURI, const stringT& location)
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
2004-05-27 10:28:26 +02:00
|
|
|
static const stringT SCHEME_MARKER = SA_.makeStringT("://");
|
2004-05-27 11:23:12 +02:00
|
|
|
static const valueT FORWARD_SLASH = SA_.makeValueT(Arabica::Unicode<char>::SLASH);
|
2004-05-27 10:28:26 +02:00
|
|
|
|
|
|
|
if(location.find(SCHEME_MARKER) != -1)
|
|
|
|
return location;
|
|
|
|
|
|
|
|
std::ostringstream ss;
|
2004-06-28 23:22:29 +02:00
|
|
|
if(location[0] == FORWARD_SLASH)
|
2004-05-27 10:28:26 +02:00
|
|
|
{
|
2004-05-27 13:48:14 +02:00
|
|
|
// prepend URI scheme and location
|
|
|
|
size_t schemeLen = baseURI.find(SCHEME_MARKER) + SCHEME_MARKER.length();
|
|
|
|
ss << baseURI.substr(0, baseURI.find(FORWARD_SLASH, schemeLen+1));
|
2004-05-27 10:28:26 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// relative
|
|
|
|
ss << baseURI;
|
|
|
|
if(baseURI.find(FORWARD_SLASH) == baseURI.length()-1)
|
|
|
|
ss << FORWARD_SLASH;
|
|
|
|
}
|
|
|
|
ss << location;
|
|
|
|
|
|
|
|
return SA_.makeStringT(ss.str().c_str());
|
|
|
|
} // absolutise
|
2004-05-12 21:36:51 +02:00
|
|
|
|
2004-06-28 23:22:29 +02:00
|
|
|
stringT absolutiseAndTrim(const stringT& baseURI, const stringT& location)
|
|
|
|
{
|
|
|
|
static const valueT FORWARD_SLASH = SA_.makeValueT(Arabica::Unicode<char>::SLASH);
|
|
|
|
|
|
|
|
stringT newlocation = absolutise(baseURI, location);
|
|
|
|
if(newlocation[newlocation.length()] == FORWARD_SLASH)
|
|
|
|
return newlocation;
|
|
|
|
|
|
|
|
return newlocation.substr(0, newlocation.rfind(FORWARD_SLASH)+1);
|
|
|
|
} // absolutiseAndTrim
|
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
stringT currentBase() const
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
if(!bases_.size())
|
|
|
|
return stringT();
|
|
|
|
return bases_.top().second;
|
|
|
|
} // currentBase()
|
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
int currentDepth() const
|
2004-05-12 21:36:51 +02:00
|
|
|
{
|
|
|
|
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_;
|
2004-05-27 10:28:26 +02:00
|
|
|
stringAdaptorT SA_;
|
2004-05-12 21:36:51 +02:00
|
|
|
|
2004-05-27 11:23:12 +02:00
|
|
|
const XMLBaseConstants<stringT, stringAdaptorT> xbc_;
|
2004-05-12 21:36:51 +02:00
|
|
|
|
|
|
|
// no impl
|
2004-05-27 11:23:12 +02:00
|
|
|
basic_XMLBaseSupport(const basic_XMLBaseSupport&);
|
|
|
|
basic_XMLBaseSupport& operator=(const basic_XMLBaseSupport&);
|
|
|
|
bool operator==(const basic_XMLBaseSupport&);
|
|
|
|
}; // class basic_XMLBaseSupport
|
|
|
|
|
|
|
|
typedef basic_XMLBaseSupport<std::string> XMLBaseSupport;
|
|
|
|
#ifndef ARABICA_NO_WCHAR_T
|
|
|
|
typedef basic_XMLBaseSupport<std::wstring> wXMLBaseSupport;
|
|
|
|
#endif
|
2004-05-27 10:28:26 +02:00
|
|
|
|
2004-05-12 21:36:51 +02:00
|
|
|
} // namespace SAX
|
|
|
|
|
|
|
|
#endif
|