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

📄 parser.cpp

📁 一个开源的网络开发库ACE
💻 CPP
📖 第 1 页 / 共 5 页
字号:
  ACEXML_Char ch = this->skip_whitespace (0);

  while (state < 2)
    {
      switch (ch)
        {
        case '?':
          if (state == 0)
            state = 1;
          break;
        case '>':
          if (state == 1)
            {
              instruction = this->obstack_.freeze ();
              this->content_handler_->processingInstruction (pitarget,
                                                             instruction ACEXML_ENV_ARG_PARAMETER);
              ACEXML_CHECK_RETURN (-1);
              this->obstack_.unwind (ACE_const_cast (ACEXML_Char*, pitarget));
              return 0;
            }
          break;
        case 0x0D:                // End-of-Line handling
          ch = (this->peek () == 0x0A ? this->get () : 0x0A);
          // Fall thru...
        case 0x0A:
          // Fall thru...
        default:
          if (state == 1)
            this->obstack_.grow ('?');
          this->obstack_.grow (ch);
          state = 0;
        }
      ch = this->get ();
    }
  return -1;
}

int
ACEXML_Parser::parse_doctypedecl (ACEXML_ENV_SINGLE_ARG_DECL)
      ACE_THROW_SPEC ((ACEXML_SAXException))
{
  if (this->parse_token (ACE_TEXT ("DOCTYPE")) < 0)
    {
      this->report_fatal_error(ACE_TEXT ("Expecting keyword 'DOCTYPE'") ACEXML_ENV_ARG_PARAMETER);
      return -1;
    }

  ACEXML_Char nextch = this->skip_whitespace (0);
  if (nextch == 0)
    {
      this->report_fatal_error(ACE_TEXT ("Expecting a DOCTYPE name") ACEXML_ENV_ARG_PARAMETER);
      return -1;
    }

  this->doctype_ = this->read_name (nextch);

  this->skip_whitespace_count (&nextch);

  if (nextch == 'S' || nextch == 'P') // ExternalID defined
    {
      this->parse_external_id_and_ref (this->dtd_public_,
                                       this->dtd_system_
                                       ACEXML_ENV_ARG_PARAMETER);
      ACEXML_CHECK_RETURN (-1);
//       if (this->dtd_public_ == 0)
//         ACE_DEBUG ((LM_DEBUG,
//                     ACE_TEXT ("ACEXML Parser got external DTD id: SYSTEM %s\n"),
//                     this->dtd_system_));
//       else
//         ACE_DEBUG ((LM_DEBUG,
//                     ACE_TEXT ("ACEXML Parser got DTD external id: PUBLIC %s %s\n"),
//                     this->dtd_public_, this->dtd_system_));
    }

  nextch = this->skip_whitespace (0);
  switch (nextch)
    {
    case '[':                   // Internal DTD definition
      if (this->parse_internal_dtd (ACEXML_ENV_SINGLE_ARG_PARAMETER) < 0)
        return -1;              // Error in markupdecl
      break;
    case '>':                   // End of DTD definition
      // this is an XML document without a dectypedecl.
      return 0;
    case '0':
      this->report_fatal_error (ACE_TEXT ("Unexpected EOF") ACEXML_ENV_ARG_PARAMETER);
      return -1;
    default:
      break;
    }

  if (this->skip_whitespace (0) != '>')
    {
      this->report_fatal_error(ACE_TEXT ("Internal error") ACEXML_ENV_ARG_PARAMETER);
      return -1;
    }
  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->read_name ();
  if (startname == 0)
    {
      this->report_fatal_error (ACE_TEXT ("Unexpected EOF") ACEXML_ENV_ARG_PARAMETER);
      return;
    }
  if (is_root && this->doctype_ != 0
      && ACE_OS::strcmp (startname, this->doctype_) != 0)
    {
      this->report_fatal_error (ACE_TEXT ("Root element missing") ACEXML_ENV_ARG_PARAMETER);
      return;
    }
  ACEXML_AttributesImpl attributes;
  ACEXML_Char ch;
  int new_namespace = 0;
  const ACEXML_Char *endname = 0;
  const ACEXML_Char *ns_uri, *ns_lname; // namespace URI and localName
  ACEXML_Char* prefix = 0;
  ACEXML_Char* name = 0;
  for (int start_element_done = 0; start_element_done == 0;)
    {
      ch = this->skip_whitespace (0);

      switch (ch)
        {
        case 0:
          this->report_fatal_error(ACE_TEXT ("Internal error") ACEXML_ENV_ARG_PARAMETER);
          return;
        case '/':
          if (this->get () != '>')
            {
              this->report_fatal_error(ACE_TEXT ("Expecting '>'") ACEXML_ENV_ARG_PARAMETER);
              return;
            }
          else
            {
              this->xml_namespace_.processName(startname, ns_uri, ns_lname, 0);
              prefix = ACE_const_cast (ACEXML_Char*,
                                       this->xml_namespace_.getPrefix(ns_uri));
              this->report_prefix_mapping (prefix, ns_uri, ns_lname, 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->report_prefix_mapping (prefix, ns_uri, ns_lname, 0 ACEXML_ENV_ARG_PARAMETER);
              ACEXML_CHECK;
            }
          if (new_namespace != 0)
            this->xml_namespace_.popContext ();
          return;

        case '>':
          {
            this->xml_namespace_.processName (startname, ns_uri, ns_lname, 0);
            prefix = ACE_const_cast (ACEXML_Char*,
                                     this->xml_namespace_.getPrefix (ns_uri));
            this->report_prefix_mapping (prefix, ns_uri, ns_lname, 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->read_name (ch);

          if (attname == 0 ||
              this->skip_equal () != 0 ||
              this->get_quoted_string (attvalue) != 0)
            {
              this->report_fatal_error(ACE_TEXT ("Error reading attribute") 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 (new_namespace == 0)
                    {
                      this->xml_namespace_.pushContext ();
                      new_namespace = 1;
                    }
                  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->report_fatal_error(ACE_TEXT ("Duplicate namespace 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 (0, 0, attname,
                                               default_attribute_type,
                                               attvalue) == -1)
                    {
                      this->report_fatal_error(ACE_TEXT ("Duplicate attribute found") ACEXML_ENV_ARG_PARAMETER);
                      return;
                    }
                }
              if (!this->namespaces_ && !this->namespace_prefixes_)
                {
                  this->report_fatal_error(ACE_TEXT ("Both namespaces feature and namespace_prefixes feature are false. Illegal Mode") 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->report_fatal_error(ACE_TEXT ("Duplicate attribute found") ACEXML_ENV_ARG_PARAMETER);
                  return;
                }
            }
          break;
        }
    }
  ACEXML_Char *cdata;
  size_t cdata_length = 0;

  // Parse element contents.
  while (1)
    {
      ACEXML_Char ch = this->get ();

      switch (ch)
        {
        case 0:
          this->report_fatal_error(ACE_TEXT ("Internal error") ACEXML_ENV_ARG_PARAMETER);
          return;
        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;
              this->obstack_.unwind (cdata);
              cdata_length = 0;
            }

          switch (this->peek ())
            {
            case '!':             // a comment or a CDATA section.
              this->get ();       // consume '!'
              ch = this->peek ();
              if (ch == '-')      // a comment
                {
                  if (this->grok_comment () < 0)
                    {
                      this->report_fatal_error(ACE_TEXT ("Error parsing comment") ACEXML_ENV_ARG_PARAMETER);
                      return;
                    }
                }
              else if (ch == '[') // a CDATA section.
                {
                  this->parse_cdata (ACEXML_ENV_SINGLE_ARG_PARAMETER);
                  ACEXML_CHECK;
                }
              else
                {
                  this->report_fatal_error(ACE_TEXT ("Unexpected character") ACEXML_ENV_ARG_PARAMETER);
                  return;
                }
              break;
            case '?':             // a PI.
              this->parse_processing_instruction (ACEXML_ENV_SINGLE_ARG_PARAMETER);
              ACEXML_CHECK;
              break;
            case '/':             // an ETag.
              {
                this->get ();       // consume '/'
                endname = this->read_name ();
                if (endname == 0 ||
                    ACE_OS::strcmp (startname, endname) != 0)
                  {
                    this->report_fatal_error(ACE_TEXT ("Mismatched End-tag encountered") ACEXML_ENV_ARG_PARAMETER);
                    return ;
                  }
                if (this->skip_whitespace (0) != '>')
                  {
                    this->report_fatal_error(ACE_TEXT ("Expecting '>' in an end-tag") ACEXML_ENV_ARG_PARAMETER);
                    return;
                  }
                this->content_handler_->endElement (ns_uri, ns_lname, endname ACEXML_ENV_ARG_PARAMETER);
                ACEXML_CHECK;
                prefix = ACE_const_cast (ACEXML_Char*,
                                         this->xml_namespace_.getPrefix(ns_uri));
                this->report_prefix_mapping (prefix, ns_uri, ns_lname, 0 ACEXML_ENV_ARG_PARAMETER);
                    ACEXML_CHECK;
                if (new_namespace != 0)
                  this->xml_namespace_.popContext ();
                return;
              }
            default:              // a new nested element?
              this->parse_element (0 ACEXML_ENV_ARG_PARAMETER);
              ACEXML_CHECK;
              break;
            }
          break;
        case '&':
          {
            const ACEXML_String *replace = 0;
            ACEXML_String charval;
            ACEXML_Char buffer[6];

            if (this->peek () == '#')
              {
                if (this->parse_char_reference (buffer, 6) != 0)
                  {
                    // not referring to any character exception?
                    return;
                  }
                charval.set (buffer, 0);
                replace = &charval;
              }
            else
              replace = this->parse_reference ();

            if (replace == 0)
              {
                this->report_fatal_error(ACE_TEXT ("Internal error") ACEXML_ENV_ARG_PARAMETER);
                return;
              }
//             if (this->try_grow_cdata (replace->length (),
//                                       cdata_length, xmlenv) == 0)
//               {
                cdata_length = replace->length ();
                for (size_t i = 0; i < replace->length (); ++i)
                  this->obstack_.grow ((*replace)[i]);
//              }
//            else
//              return;
          }
          break;
        case 0x0D:                // End-of-Line handling
          ch = (this->peek () == 0x0A ? this->get () : 0x0A);
          // Fall thru...
        case 0x0A:
          // Fall thru...
        default:
          ++cdata_length;
          cdata = this->obstack_.grow (ch);
          if (cdata == 0)
            {
              cdata = this->obstack_.freeze ();
              this->content_handler_->characters (cdata,
                                                  0,
                                                  cdata_length ACEXML_ENV_ARG_PARAMETER);
              ACEXML_CHECK;
              this->obstack_.grow (ch);
              cdata_length = 1;   // the missing char.
            }
        }
    }
  ACE_NOTREACHED (return;)
}

int
ACEXML_Parser::parse_char_reference (ACEXML_Char *buf, size_t len)
{
  if (this->get () != '#')
    {
      // Internal error.
      return -1;
    }

  int hex = 0;

  if (this->peek () == 'x')
    {
      hex = 1;
      this->get ();
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -