mirror of
https://github.com/jezhiggins/arabica
synced 2024-12-26 21:58:39 +01:00
211 lines
6.4 KiB
C++
211 lines
6.4 KiB
C++
#ifndef JEZUK_SIMPLEDOM_ATTRIMPL_H
|
|
#define JEZUK_SIMPLEDOM_ATTRIMPL_H
|
|
|
|
#include <DOM/Attr.hpp>
|
|
#include <DOM/Simple/NodeImpl.hpp>
|
|
#include <DOM/Simple/TextImpl.hpp>
|
|
#include <DOM/Simple/DocumentTypeImpl.hpp>
|
|
|
|
namespace Arabica
|
|
{
|
|
namespace SimpleDOM
|
|
{
|
|
|
|
template<class stringT, class string_adaptorT> class ElementImpl;
|
|
|
|
template<class stringT, class string_adaptorT>
|
|
class AttrImpl : public DOM::Attr_impl<stringT, string_adaptorT>,
|
|
public NodeImplWithChildren<stringT, string_adaptorT>
|
|
{
|
|
public:
|
|
typedef NodeImplWithChildren<stringT, string_adaptorT> NodeT;
|
|
typedef ElementImpl<stringT, string_adaptorT> ElementImplT;
|
|
typedef DOM::Attr_impl<stringT, string_adaptorT> DOMAttr_implT;
|
|
typedef DOM::Element_impl<stringT, string_adaptorT> DOMElement_implT;
|
|
typedef DOM::Node_impl<stringT, string_adaptorT> DOMNode_implT;
|
|
|
|
AttrImpl(DocumentImpl<stringT, string_adaptorT>* ownerDoc, const stringT& name) :
|
|
DOMAttr_implT(),
|
|
NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc),
|
|
name_(ownerDoc->stringPool(name)),
|
|
ownerElement_(0),
|
|
specified_(true),
|
|
valueCalculated_(false)
|
|
{
|
|
} // AttrImpl
|
|
|
|
AttrImpl(DocumentImpl<stringT, string_adaptorT>* ownerDoc, const stringT& name, const stringT& value) :
|
|
DOMAttr_implT(),
|
|
NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc),
|
|
name_(ownerDoc->stringPool(name)),
|
|
ownerElement_(0),
|
|
specified_(true),
|
|
valueCalculated_(false)
|
|
{
|
|
setNodeValue(value);
|
|
} // AttrImpl
|
|
|
|
virtual ~AttrImpl() { }
|
|
|
|
///////////////////////////////////////////////////
|
|
// DOM::Attribute methods
|
|
virtual const stringT& getName() const { return getNodeName(); }
|
|
|
|
virtual bool getSpecified() const
|
|
{
|
|
return specified_;
|
|
} // getSpecified
|
|
|
|
const stringT& getValue() const { return getNodeValue(); }
|
|
void setValue(const stringT& value) { setNodeValue(value); }
|
|
|
|
virtual DOMElement_implT* getOwnerElement() const
|
|
{
|
|
return ownerElement_;
|
|
} // getOwnerElement
|
|
|
|
/////////////////////////////////////////////////////
|
|
// DOM::Node methods
|
|
virtual typename DOM::Node_base::Type getNodeType() const
|
|
{
|
|
return DOM::Node_base::ATTRIBUTE_NODE;
|
|
} // getNodeType
|
|
|
|
virtual DOMNode_implT* getParentNode() const { return 0; }
|
|
virtual DOMNode_implT* getPreviousSibling() const { return 0; }
|
|
virtual DOMNode_implT* getNextSibling() const { return 0; }
|
|
|
|
virtual DOMNode_implT* insertBefore(DOMNode_implT* newChild, DOMNode_implT* refChild)
|
|
{
|
|
valueCalculated_ = false;
|
|
return NodeT::insertBefore(newChild, refChild);
|
|
} // insertBefore
|
|
|
|
virtual DOMNode_implT* replaceChild(DOMNode_implT* newChild, DOMNode_implT* oldChild)
|
|
{
|
|
valueCalculated_ = false;
|
|
return NodeT::replaceChild(newChild, oldChild);
|
|
} // replaceChild
|
|
|
|
virtual DOMNode_implT* removeChild(DOMNode_implT* oldChild)
|
|
{
|
|
valueCalculated_ = false;
|
|
return NodeT::removeChild(oldChild);
|
|
} // removeChild
|
|
|
|
virtual DOMNode_implT* appendChild(DOMNode_implT* newChild)
|
|
{
|
|
valueCalculated_ = false;
|
|
return NodeT::appendChild(newChild);
|
|
} // appendChild
|
|
|
|
virtual void purgeChild(DOMNode_implT* oldChild)
|
|
{
|
|
valueCalculated_ = false;
|
|
NodeT::purgeChild(oldChild);
|
|
} // purgeChild
|
|
|
|
virtual DOMNode_implT* cloneNode(bool /*deep*/) const
|
|
{
|
|
AttrImpl* a = dynamic_cast<AttrImpl*>(NodeT::ownerDoc_->createAttribute(*name_));
|
|
cloneChildren(a);
|
|
a->setSpecified(getSpecified());
|
|
return a;
|
|
} // cloneNode
|
|
|
|
virtual const stringT& getNodeName() const
|
|
{
|
|
return *name_;
|
|
} // getNodeName
|
|
|
|
virtual const stringT& getNodeValue() const
|
|
{
|
|
if(!valueCalculated_)
|
|
{
|
|
value_ = concatNodes(NodeT::getFirstChild());
|
|
valueCalculated_ = true;
|
|
}
|
|
return value_;
|
|
} // getNodeValue
|
|
|
|
virtual void setNodeValue(const stringT& data)
|
|
{
|
|
NodeT::throwIfReadOnly();
|
|
|
|
// remove all children
|
|
for(DOMNode_implT* c = NodeT::getFirstChild(); c != 0; c = NodeT::getFirstChild())
|
|
NodeT::removeChild(c);
|
|
|
|
// add a new text node
|
|
NodeT::appendChild(NodeT::ownerDoc_->createTextNode(data));
|
|
|
|
valueCalculated_ = false;
|
|
specified_ = true;
|
|
} // setNodeValue
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// this implementation
|
|
void setOwnerElement(ElementImplT* element)
|
|
{
|
|
ownerElement_ = element;
|
|
if(NodeT::ownerDoc_)
|
|
{
|
|
NodeT::ownerDoc_->adopted(this); // don't have a parent but are owned
|
|
DocumentTypeImpl<stringT, string_adaptorT>* docType = dynamic_cast<DocumentTypeImpl<stringT, string_adaptorT>*>(NodeT::ownerDoc_->getDoctype());
|
|
if(!docType || docType->getElementIds()->empty())
|
|
return;
|
|
std::vector<stringT>* elemIds = docType->getElementIds();
|
|
if(std::find(elemIds->begin(), elemIds->end(), *name_) != elemIds->end())
|
|
NodeT::ownerDoc_->setElementId(this);
|
|
} // if(ownerDoc_)
|
|
} // setOwnerElement
|
|
|
|
void setSpecified(bool specified) { specified_ = specified; }
|
|
|
|
bool isOrphaned()
|
|
{
|
|
if(!ownerElement_)
|
|
return true;
|
|
|
|
return NodeT::ownerDoc_->isOrphaned(this);
|
|
} // isOrphaned
|
|
|
|
protected:
|
|
void cloneChildren(AttrImpl* clone) const
|
|
{
|
|
for(DOMNode_implT* c = NodeT::getFirstChild(); c != 0; c = c->getNextSibling())
|
|
clone->appendChild(c->cloneNode(true));
|
|
} // cloneChildren
|
|
|
|
private:
|
|
stringT concatNodes(DOMNode_implT* firstChild) const
|
|
{
|
|
stringT value;
|
|
for(DOMNode_implT* c = firstChild; c != 0; c = c->getNextSibling())
|
|
if(c->getNodeType() == DOM::Node_base::ENTITY_REFERENCE_NODE)
|
|
string_adaptorT::append(value, concatNodes(c->getFirstChild()));
|
|
else
|
|
string_adaptorT::append(value, c->getNodeValue());
|
|
return value;
|
|
} // concatNodes
|
|
|
|
virtual void checkChildType(DOMNode_implT* child)
|
|
{
|
|
typename DOM::Node_base::Type type = child->getNodeType();
|
|
if((type != DOM::Node_base::TEXT_NODE) &&
|
|
(type != DOM::Node_base::ENTITY_REFERENCE_NODE))
|
|
throw DOM::DOMException(DOM::DOMException::HIERARCHY_REQUEST_ERR);
|
|
} // checkChildType
|
|
|
|
protected:
|
|
stringT const* name_;
|
|
ElementImplT* ownerElement_;
|
|
bool specified_;
|
|
mutable bool valueCalculated_;
|
|
mutable stringT value_;
|
|
}; // class AttrImpl
|
|
|
|
} // namespace SimpleDOM
|
|
} // namespace Arabica
|
|
|
|
#endif
|