📄 parser.cpp
字号:
ACEXML_Parser::parse_external_id (ACEXML_Char *&publicId,
ACEXML_Char *&systemId
ACEXML_ENV_ARG_DECL)
ACE_THROW_SPEC ((ACEXML_SAXException))
{
publicId = systemId = 0;
ACEXML_Char nextch = this->get ();
ACEXML_Char fwd = 0;
switch (nextch)
{
case 'S': // External SYSTEM id.
if (this->parse_token (ACE_TEXT ("YSTEM")) < 0 ||
this->skip_whitespace_count () < 1)
{
this->fatal_error(ACE_TEXT ("Expecting keyword SYSTEM")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
if (this->parse_system_literal (systemId) != 0)
{
this->fatal_error(ACE_TEXT ("Invalid systemLiteral")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
break;
case 'P': // External PUBLIC id or previously defined PUBLIC id.
if (this->parse_token (ACE_TEXT ("UBLIC")) < 0 ||
this->skip_whitespace_count () < 1)
{
this->fatal_error(ACE_TEXT ("Expecing keyword PUBLIC")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
if (this->parse_pubid_literal (publicId) != 0)
{
this->fatal_error(ACE_TEXT ("Invalid PubidLiteral")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
this->skip_whitespace_count(&fwd);
if (fwd == '\'' || fwd == '"')
{
if (this->parse_system_literal (systemId) != 0)
{
this->fatal_error(ACE_TEXT ("Invalid systemLiteral")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
}
else if (this->ref_state_ != ACEXML_ParserInt::IN_NOTATION)
{
this->fatal_error(ACE_TEXT ("Expecting systemLiteral after a ")
ACE_TEXT ("PUBLIC keyword")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
break;
default:
this->fatal_error(ACE_TEXT ("Invalid system/public Literal")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
return 0;
}
ACEXML_Char*
ACEXML_Parser::normalize_systemid (const ACEXML_Char* systemId)
{
if (ACE_OS::strstr (systemId, ACE_TEXT("ftp://")) != 0 ||
ACE_OS::strstr (systemId, ACE_TEXT ("http://")) != 0 ||
ACE_OS::strstr (systemId, ACE_TEXT ("file://")) != 0)
return 0;
else
{
ACEXML_Char* normalized_uri = 0;
const ACEXML_Char* baseURI = this->current_->getLocator()->getSystemId();
ACE_ASSERT (baseURI);
const ACEXML_Char* temp = 0;
if (ACE_OS::strstr (baseURI, ACE_TEXT ("http://")) != 0)
// baseURI is a HTTP URL and systemId is relative. Note that this
// is not compliant with RFC2396. Caveat Emptor !
temp = ACE_OS::strrchr (baseURI, '/');
else
// baseURI is a local file and systemId is relative
// Unlike the HTTP one, this will work always.
temp = ACE_OS::strrchr (baseURI,ACE_DIRECTORY_SEPARATOR_CHAR);
if (temp)
{
size_t pos = temp - baseURI + 1;
size_t len = pos + ACE_OS::strlen (systemId) + 1;
ACE_NEW_RETURN (normalized_uri, ACEXML_Char[len], 0);
ACE_OS::strncpy (normalized_uri, baseURI, pos);
ACE_OS::strcpy (normalized_uri + pos, systemId);
return normalized_uri;
}
return 0;
}
}
void
ACEXML_Parser::parse_element (int is_root ACEXML_ENV_ARG_DECL)
ACE_THROW_SPEC ((ACEXML_SAXException))
{
// Parse STag.
const ACEXML_Char *startname = this->parse_name ();
if (startname == 0)
{
this->fatal_error (ACE_TEXT ("Unexpected end-of-file")
ACEXML_ENV_ARG_PARAMETER);
return;
}
if (is_root && this->doctype_ != 0
&& ACE_OS::strcmp (startname, this->doctype_) != 0)
{
this->fatal_error (ACE_TEXT ("Root element different from DOCTYPE")
ACEXML_ENV_ARG_PARAMETER);
return ;
}
ACEXML_AttributesImpl attributes;
ACEXML_Char ch;
int ns_flag = 0; // Push only one namespace context onto the stack
// if there are multiple namespaces declared.
const ACEXML_Char* ns_uri = 0;
const ACEXML_Char* ns_lname = 0; // namespace URI and localName
for (int start_element_done = 0; start_element_done == 0;)
{
ch = this->skip_whitespace ();
switch (ch)
{
case 0:
this->fatal_error(ACE_TEXT ("Internal Parser error")
ACEXML_ENV_ARG_PARAMETER);
return;
case '/':
if (this->get () != '>')
{
this->fatal_error(ACE_TEXT ("Expecting '>' at end of element ")
ACE_TEXT ("definition")
ACEXML_ENV_ARG_PARAMETER);
return;
}
this->xml_namespace_.processName(startname, ns_uri,
ns_lname, 0);
this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
ns_uri, 1
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
this->content_handler_->startElement(ns_uri, ns_lname,
startname, &attributes
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
this->content_handler_->endElement (ns_uri, ns_lname, startname
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
ns_uri, 0
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
if (ns_flag)
{
this->xml_namespace_.popContext ();
this->nested_namespace_--;
}
return;
case '>':
this->xml_namespace_.processName (startname, ns_uri,
ns_lname, 0);
this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
ns_uri, 1
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
this->content_handler_->startElement(ns_uri, ns_lname, startname,
&attributes
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
start_element_done = 1;
break;
default:
ACEXML_Char *attvalue = 0;
ACEXML_Char *attname = this->parse_name (ch);
if (attname == 0 ||
this->skip_equal () != 0 ||
this->parse_attvalue (attvalue ACEXML_ENV_ARG_PARAMETER) != 0)
{
this->fatal_error(ACE_TEXT ("Error reading attribute value")
ACEXML_ENV_ARG_PARAMETER);
return;
}
// Handling new namespace if any. Notice that the order of
// namespace declaration does matter.
if (ACE_OS::strncmp (attname, ACE_TEXT("xmlns"), 5) == 0)
{
if (this->namespaces_)
{
if (!ns_flag)
{
this->xml_namespace_.pushContext ();
this->nested_namespace_++;
ns_flag = 1;
}
ACEXML_Char* name = ACE_OS::strchr (attname, ':');
const ACEXML_Char* ns_name = (name == 0)?
empty_string:name+1;
if (this->xml_namespace_.declarePrefix (ns_name,
attvalue) == -1)
{
this->fatal_error(ACE_TEXT ("Duplicate definition of ")
ACE_TEXT ("prefix")
ACEXML_ENV_ARG_PARAMETER);
return;
}
}
if (this->namespace_prefixes_)
{
// Namespace_prefixes_feature_ is required. So add the
// xmlns:foo to the list of attributes.
if (attributes.addAttribute (ACE_TEXT (""), ACE_TEXT (""),
attname,
default_attribute_type,
attvalue) == -1)
{
this->fatal_error(ACE_TEXT ("Duplicate attribute ")
ACE_TEXT ("definition. Hint: Try ")
ACE_TEXT ("setting namespace_prefix")
ACE_TEXT ("es feature to 0")
ACEXML_ENV_ARG_PARAMETER);
return;
}
}
if (!this->namespaces_ && !this->namespace_prefixes_)
{
this->fatal_error(ACE_TEXT ("One of namespaces or ")
ACE_TEXT ("namespace_prefixes should be")
ACE_TEXT (" declared")
ACEXML_ENV_ARG_PARAMETER);
return;
}
}
else
{
const ACEXML_Char *uri, *lName;
this->xml_namespace_.processName (attname, uri, lName, 1);
if (attributes.addAttribute (uri, lName, attname,
default_attribute_type,
attvalue) == -1)
{
this->fatal_error(ACE_TEXT ("Duplicate attribute ")
ACE_TEXT ("definition")
ACEXML_ENV_ARG_PARAMETER);
return;
}
}
break;
}
}
if (this->parse_content (startname, ns_uri, ns_lname, ns_flag
ACEXML_ENV_ARG_PARAMETER) != 0)
return;
}
int
ACEXML_Parser::parse_content (const ACEXML_Char* startname,
const ACEXML_Char*& ns_uri,
const ACEXML_Char*& ns_lname, int ns_flag ACEXML_ENV_ARG_DECL)
ACE_THROW_SPEC ((ACEXML_SAXException))
{
ACEXML_Char *cdata;
size_t cdata_length = 0;
// Parse element contents.
while (1)
{
ACEXML_Char ch = this->get ();
switch (ch)
{
case 0:
this->pop_context (1 ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
break;
case '<':
// Push out old 'characters' event.
if (cdata_length != 0)
{
cdata = this->obstack_.freeze ();
this->content_handler_->characters (cdata, 0, cdata_length
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
this->obstack_.unwind (cdata);
cdata_length = 0;
}
ch = this->peek();
switch (ch)
{
case '!': // a comment or a CDATA section.
this->get (); // consume '!'
ch = this->peek ();
if (ch == '-') // a comment
{
if (this->parse_comment () < 0)
{
this->fatal_error(ACE_TEXT ("Invalid comment in ")
ACE_TEXT ("document")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
}
else if (ch == '[') // a CDATA section.
{
this->parse_cdata (ACEXML_ENV_SINGLE_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
else
{
this->fatal_error(ACE_TEXT ("Expecting a CDATA section ")
ACE_TEXT ("or a comment section")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
break;
case '?': // a PI.
this->get(); // consume the '?'
this->parse_processing_instruction
(ACEXML_ENV_SINGLE_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
break;
case '/': // an ETag.
{
this->get (); // consume '/'
ACEXML_Char* endname = this->parse_name ();
if (endname == 0 ||
ACE_OS::strcmp (startname, endname) != 0)
{
this->fatal_error(ACE_TEXT ("Name in ETag doesn't ")
ACE_TEXT ("match name in STag")
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
}
if (this->skip_whitespace () != '>')
{
this->fatal_error(ACE_TEXT ("Expecting '>' at end ")
ACE_TEXT ("of element")
ACEXML_ENV_ARG_PARAMETER);
return -1;
}
this->content_handler_->endElement (ns_uri, ns_lname,
endname
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
ns_uri, 0
ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
if (this->namespaces_ && ns_flag)
{
if (this->nested_namespace_ >= 1)
{
this->xml_namespace_.popContext ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -