Ejemplo n.º 1
0
bool IWORKParser::parse()
{
  const shared_ptr<xmlTextReader> sharedReader(xmlReaderForIO(readFromStream, closeStream, m_input.get(), "", nullptr, 0), xmlFreeTextReader);
  if (!sharedReader)
    return false;

  xmlTextReaderPtr reader = sharedReader.get();
  assert(reader);

  const IWORKTokenizer &tokenizer = getTokenizer();
  stack<IWORKXMLContextPtr_t> contextStack;

  int ret = xmlTextReaderRead(reader);
  contextStack.push(createDocumentContext());

  bool keynoteDocTypeChecked=false;
  char const *defaultNS=nullptr;
  while ((1 == ret))
  {
    switch (xmlTextReaderNodeType(reader))
    {
    case XML_READER_TYPE_ELEMENT:
    {
      if (!keynoteDocTypeChecked)
      {
        // check for keynote 1 file with doctype node and not a namespace in first node
        keynoteDocTypeChecked=true;
        if (xmlTextReaderNodeType(reader)==XML_READER_TYPE_ELEMENT &&
            xmlTextReaderConstNamespaceUri(reader)==nullptr)
          defaultNS="http://developer.apple.com/schemas/APXL";
      }
      const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)),
                                              defaultNS ? defaultNS : char_cast(xmlTextReaderConstNamespaceUri(reader)));

      IWORKXMLContextPtr_t newContext = contextStack.top()->element(id);

      if (!newContext)
        newContext = createDiscardContext();

      const bool isEmpty = xmlTextReaderIsEmptyElement(reader);

      newContext->startOfElement();
      if (xmlTextReaderHasAttributes(reader))
      {
        ret = xmlTextReaderMoveToFirstAttribute(reader);
        while (1 == ret)
        {
          processAttribute(reader, newContext, tokenizer);
          ret = xmlTextReaderMoveToNextAttribute(reader);
        }
      }

      if (isEmpty)
        newContext->endOfElement();
      else
        contextStack.push(newContext);

      break;
    }
    case XML_READER_TYPE_END_ELEMENT:
    {
      contextStack.top()->endOfElement();
      contextStack.pop();
      break;
    }
    case XML_READER_TYPE_CDATA :
    {
      const xmlChar *text = xmlTextReaderConstValue(reader);
      if (text) contextStack.top()->CDATA(char_cast(text));
      break;
    }
    case XML_READER_TYPE_TEXT :
    {
      xmlChar *const text = xmlTextReaderReadString(reader);
      contextStack.top()->text(char_cast(text));
      xmlFree(text);
      break;
    }
    default:
      break;
    }

    ret = xmlTextReaderRead(reader);

  }

  while (!contextStack.empty()) // finish parsing in case of broken XML
  {
    contextStack.top()->endOfElement();
    contextStack.pop();
  }
  xmlTextReaderClose(reader);

  return true;
}
Ejemplo n.º 2
0
bool IWORKParser::parse()
{
  const shared_ptr<xmlTextReader> sharedReader(xmlReaderForIO(readFromStream, closeStream, m_input.get(), "", 0, 0), xmlFreeTextReader);
  if (!sharedReader)
    return false;

  xmlTextReaderPtr reader = sharedReader.get();
  assert(reader);

  const IWORKTokenizer &tokenizer = getTokenizer();
  stack<IWORKXMLContextPtr_t> contextStack;

  int ret = xmlTextReaderRead(reader);
  contextStack.push(createDocumentContext());

  while ((1 == ret))
  {
    switch (xmlTextReaderNodeType(reader))
    {
    case XML_READER_TYPE_ELEMENT:
    {
      const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));

      IWORKXMLContextPtr_t newContext = contextStack.top()->element(id);

      if (!newContext)
        newContext = createDiscardContext();

      const bool isEmpty = xmlTextReaderIsEmptyElement(reader);

      newContext->startOfElement();
      if (xmlTextReaderHasAttributes(reader))
      {
        ret = xmlTextReaderMoveToFirstAttribute(reader);
        while (1 == ret)
        {
          processAttribute(reader, newContext, tokenizer);
          ret = xmlTextReaderMoveToNextAttribute(reader);
        }
      }

      if (isEmpty)
        newContext->endOfElement();
      else
        contextStack.push(newContext);

      break;
    }
    case XML_READER_TYPE_END_ELEMENT:
    {
      contextStack.top()->endOfElement();
      contextStack.pop();
      break;
    }
    case XML_READER_TYPE_TEXT :
    {
      xmlChar *const text = xmlTextReaderReadString(reader);
      contextStack.top()->text(char_cast(text));
      xmlFree(text);
      break;
    }
    default:
      break;
    }

    ret = xmlTextReaderRead(reader);

  }

  while (!contextStack.empty()) // finish parsing in case of broken XML
  {
    contextStack.top()->endOfElement();
    contextStack.pop();
  }
  xmlTextReaderClose(reader);

  return true;
}