📄 dom_document.cpp
字号:
/* $Id: dom_document.cpp,v 1.20 2004/01/02 10:37:41 mbn Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Core/precomp.h"
#include "API/Core/XML/dom_document.h"
#include "API/Core/XML/dom_document_type.h"
#include "API/Core/XML/dom_implementation.h"
#include "API/Core/XML/dom_element.h"
#include "API/Core/XML/dom_document_fragment.h"
#include "API/Core/XML/dom_text.h"
#include "API/Core/XML/dom_comment.h"
#include "API/Core/XML/dom_cdata_section.h"
#include "API/Core/XML/dom_processing_instruction.h"
#include "API/Core/XML/dom_attr.h"
#include "API/Core/XML/dom_entity_reference.h"
#include "API/Core/XML/dom_node_list.h"
#include "API/Core/XML/xml_tokenizer.h"
#include "API/Core/XML/xml_writer.h"
#include "API/Core/XML/xml_token.h"
#include "dom_document_generic.h"
#include <stack>
#include "API/Core/XML/xml_token_load.h"
#include "API/Core/XML/xml_token_save.h"
#include "API/Core/XML/xml_token_string.h"
/////////////////////////////////////////////////////////////////////////////
// CL_DomDocument construction:
CL_DomDocument::CL_DomDocument() : CL_DomNode(new CL_DomDocument_Generic)
{
}
CL_DomDocument::CL_DomDocument(CL_InputSource *input, bool delete_input, bool eat_whitespace)
: CL_DomNode(new CL_DomDocument_Generic)
{
load(input, delete_input, eat_whitespace);
}
CL_DomDocument::CL_DomDocument(CL_DomNode_Generic *impl) : CL_DomNode(impl)
{
}
CL_DomDocument::~CL_DomDocument()
{
}
/////////////////////////////////////////////////////////////////////////////
// CL_DomDocument attributes:
CL_DomDocumentType CL_DomDocument::get_doctype()
{
return CL_DomDocumentType(*this);
}
CL_DomImplementation CL_DomDocument::get_implementation()
{
return CL_DomImplementation(*this);
}
CL_DomElement CL_DomDocument::get_document_element()
{
CL_DomNode cur(impl->first_child);
while (!cur.is_null())
{
if (cur.is_element()) return cur.to_element();
cur = cur.get_next_sibling();
}
return CL_DomElement();
}
/////////////////////////////////////////////////////////////////////////////
// CL_DomDocument operations:
CL_DomElement CL_DomDocument::create_element(const std::string &tag_name)
{
return CL_DomElement(*this, tag_name);
}
CL_DomDocumentFragment CL_DomDocument::create_document_fragment()
{
return CL_DomDocumentFragment(*this);
}
CL_DomText CL_DomDocument::create_text_node(const std::string &data)
{
return CL_DomText(*this, data);
}
CL_DomComment CL_DomDocument::create_comment(const std::string &data)
{
return CL_DomComment(*this, data);
}
CL_DomCDATASection CL_DomDocument::create_cdata_section(const std::string &data)
{
return CL_DomCDATASection(*this, data);
}
CL_DomProcessingInstruction CL_DomDocument::create_processing_instruction(
const std::string &target,
const std::string &data)
{
return CL_DomProcessingInstruction(*this, target, data);
}
CL_DomAttr CL_DomDocument::create_attribute(const std::string &name)
{
return CL_DomAttr(*this, name);
}
CL_DomEntityReference CL_DomDocument::create_entity_reference(const std::string &name)
{
return CL_DomEntityReference(*this, name);
}
CL_DomNodeList CL_DomDocument::get_elements_by_tag_name(const std::string &tag_name)
{
return CL_DomNodeList(*this, tag_name);
}
void CL_DomDocument::load(CL_InputSource *input, bool delete_input, bool eat_whitespace)
{
CL_XMLTokenizer tokenizer(input, delete_input);
tokenizer.set_eat_whitespace(eat_whitespace);
std::stack<CL_DomNode> node_stack;
node_stack.push(*this);
CL_XMLTokenLoad cur_token = tokenizer.next();
while (cur_token.get_type() != CL_XMLToken::NULL_TOKEN)
{
switch (cur_token.get_type())
{
case CL_XMLToken::TEXT_TOKEN:
node_stack.top().append_child(create_text_node(cur_token.get_value()));
break;
case CL_XMLToken::CDATA_SECTION_TOKEN:
node_stack.top().append_child(create_cdata_section(cur_token.get_value()));
break;
case CL_XMLToken::ELEMENT_TOKEN:
if (cur_token.get_variant() != CL_XMLToken::END)
{
CL_DomElement element = create_element(cur_token.get_name());
node_stack.top().append_child(element);
//const std::vector< std::pair<std::string, std::string> > &attributes = cur_token.get_attributes();
int size = cur_token.get_attributes_number();
for (int i=0; i<size; i++)
{
// std::pair<std::string, std::string> attribute(cur_token.get_attribute(i));
std::pair<CL_XMLTokenString, CL_XMLTokenString> const & attribute = cur_token.get_attribute_fast(i);
element.set_attribute(attribute.first.to_string(), attribute.second.to_string());
}
if (cur_token.get_variant() == CL_XMLToken::BEGIN)
node_stack.push(element);
}
else
{
node_stack.pop();
if (node_stack.empty()) throw CL_Error("Malformed XML tree!");
}
break;
case CL_XMLToken::NULL_TOKEN:
break;
case CL_XMLToken::ENTITY_REFERENCE_TOKEN:
break;
case CL_XMLToken::ENTITY_TOKEN:
break;
case CL_XMLToken::COMMENT_TOKEN:
break;
case CL_XMLToken::DOCUMENT_TYPE_TOKEN:
break;
case CL_XMLToken::NOTATION_TOKEN:
break;
case CL_XMLToken::PROCESSING_INSTRUCTION_TOKEN:
break;
}
cur_token = tokenizer.next();
}
}
void CL_DomDocument::save(CL_OutputSource *output, bool delete_output, bool insert_whitespace)
{
CL_XMLWriter writer(output, delete_output);
writer.set_insert_whitespace(insert_whitespace);
std::stack<CL_DomNode> node_stack;
CL_DomNode cur_node = get_first_child();
while (!cur_node.is_null())
{
// Create opening node:
CL_XMLTokenSave opening_node;
opening_node.set_type((CL_XMLToken::TokenType) cur_node.get_node_type());
opening_node.set_variant(cur_node.has_child_nodes() ? CL_XMLToken::BEGIN : CL_XMLToken::SINGLE);
opening_node.set_name(cur_node.get_node_name());
opening_node.set_value(cur_node.get_node_value());
if (cur_node.is_element())
{
std::vector<std::pair<std::string, CL_DomNode_Generic *> >::iterator it;
for (it = cur_node.impl->attributes.begin(); it != cur_node.impl->attributes.end(); ++it)
{
opening_node.set_attribute(it->first, it->second->node_value);
}
}
writer.write(opening_node);
// Create any possible child nodes:
if (cur_node.has_child_nodes())
{
node_stack.push(cur_node);
cur_node = cur_node.get_first_child();
continue;
}
// Create closing nodes until we reach next opening node in tree:
while (true)
{
if (cur_node.has_child_nodes())
{
CL_XMLTokenSave closing_node;
closing_node.set_type((CL_XMLToken::TokenType) cur_node.get_node_type());
closing_node.set_name(cur_node.get_node_name());
closing_node.set_variant(CL_XMLToken::END);
writer.write(closing_node);
}
cur_node = cur_node.get_next_sibling();
if (!cur_node.is_null()) break;
if (node_stack.empty()) break;
cur_node = node_stack.top();
node_stack.pop();
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CL_DomDocument implementation:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -