⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.cpp

📁 ACE编程的一本经典BIBLE的源代码,喜欢网络编程的别错过
💻 CPP
📖 第 1 页 / 共 5 页
字号:
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 + -