Beispiel #1
0
void CXMLparser::ProcessEntity (void)
  {
CString strName;
CString strValue;
CString strTemp;

  strName = GetName ("entity");

  strTemp = strName.Left (3);
  strTemp.MakeUpper ();

  if (strTemp == "XML")
    ThrowErrorException ("Names starting with \"XML\" are reserved");

  strValue = GetValue ("entity", strName);

  // entities might have entities in them, so replace them
  m_CustomEntityMap.SetAt (strName, ReplaceEntities (strValue));

  if (m_xmlBuff [m_xmlPos] != '>')
    ThrowErrorException ("Expected '>', got %c",
        m_xmlBuff [m_xmlPos]);

  m_xmlPos++;   // skip >

  // bypass spaces and comments

  SkipComments (true);

  } // end of CXMLparser::ProcessEntity 
Beispiel #2
0
void csWrappedDocumentNode::ProcessSingleWrappedNode (
  NodeProcessingState* state, iDocumentNode* node)
{
  CS_ASSERT(globalState);

  if (ProcessTemplate (node, state)) return;
  if (ProcessStaticIf (state, node))
  {
    // Template invokation has precedence over dropping nodes...
    TempString<> tokenStr, args; 
    if (SplitNodeValue (node->GetValue(), tokenStr, args))
    {
      Template::Params params;
      if (!args.IsEmpty())
      {
        ParseTemplateArguments (args, params, false);
      }
      InvokeTemplate (tokenStr, node, state, params);
    }
    return;
  }

  csRefArray<iDocumentNode>& currentWrapper = state->currentWrapper;
  bool handled = false;
  if (node->GetType() == CS_NODE_UNKNOWN)
  {
    TempString<> replaceScratch;
    const char* nodeValue = ReplaceEntities (node->GetValue(),
      replaceScratch);
    if ((nodeValue != 0) && (*nodeValue == '?') && 
      (*(nodeValue + strlen (nodeValue) - 1) == '?'))
    {
      const char* valStart = nodeValue + 1;
      if ((*valStart == '!') || (*valStart == '#'))
      {
	/* Discard PIs beginning with ! and #. This allows comments, e.g.
	 * <?! some comment ?>
	 * The difference to XML comments is that the PI comments do not
	 * appear in the final document after processing, hence are useful
	 * if some PIs themselves are to be commented, but it is undesireable
	 * to have an XML comment in the result. */
	return;
      }

      while (*valStart == ' ') valStart++;
      CS_ASSERT (*valStart != 0);
      size_t valLen = strlen (valStart) - 1;
      if (valLen == 0)
      {
	Report (syntaxErrorSeverity, node,
	  "Empty processing instruction");
      }
      else
      {
	while (*(valStart + valLen - 1) == ' ') valLen--;
	const char* space = strchr (valStart, ' ');
	/* The rightmost spaces were skipped and don't interest us
	    any more. */
	if (space >= valStart + valLen) space = 0;
	size_t cmdLen;
	if (space != 0)
	{
	  cmdLen = space - valStart;
	}
	else
	{
	  cmdLen = valLen;
	}

	TempString<> tokenStr; tokenStr.Replace (valStart, cmdLen);
	csStringID tokenID = shared->pitokens.Request (tokenStr);
	switch (tokenID)
	{
	  case csWrappedDocumentNodeFactory::PITOKEN_INCLUDE:
            if (shared->plugin->do_verbose)
            {
              Report (CS_REPORTER_SEVERITY_WARNING, node,
                "Deprecated syntax, please use %s",
		CS::Quote::Single ("Include"));
            }
            // Fall through
	  case csWrappedDocumentNodeFactory::PITOKEN_INCLUDE_NEW:
	    {
	      bool okay = true;
	      TempString<> filename;
	      const char* space = strchr (valStart, ' ');
	      /* The rightmost spaces were skipped and don't interest us
	       * any more. */
	      if (space != 0)
	      {
		filename.Replace (space + 1, valLen - cmdLen - 1);
		filename.Trim ();
	      }
	      if ((space == 0) || (filename.IsEmpty ()))
	      {
		Report (syntaxErrorSeverity, node,
		  "%s without filename", CS::Quote::Single ("Include"));
		okay = false;
	      }
	      if (okay)
	      {
		ProcessInclude (filename, state, node);
	      }
	      handled = true;
	    }
	    break;
	  case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATE:
            if (shared->plugin->do_verbose)
            {
              Report (CS_REPORTER_SEVERITY_WARNING, node,
                "Deprecated syntax, please use %s",
		CS::Quote::Single ("Template"));
            }
            // Fall through
          case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATE_NEW:
	  case csWrappedDocumentNodeFactory::PITOKEN_TEMPLATEWEAK:
            {
              TempString<> args (valStart + cmdLen, valLen - cmdLen);
              args.LTrim();
              ProcessInstrTemplate (state, node, args, 
                tokenID == csWrappedDocumentNodeFactory::PITOKEN_TEMPLATEWEAK);
	      handled = true;
            }
	    break;
	  case csWrappedDocumentNodeFactory::PITOKEN_ENDTEMPLATE:
            if (shared->plugin->do_verbose)
            {
              Report (CS_REPORTER_SEVERITY_WARNING, node,
                "Deprecated syntax, please use %s",
		CS::Quote::Single ("Endtemplate"));
	      handled = true;
            }
            // Fall through
	  case csWrappedDocumentNodeFactory::PITOKEN_ENDTEMPLATE_NEW:
	    {
	      Report (syntaxErrorSeverity, node,
		"%s without %s",
		CS::Quote::Single ("Endtemplate"),
		CS::Quote::Single ("Template"));
              // ProcessTemplate() would've handled it otherwise
	      handled = true;
	    }
	    break;
          case csWrappedDocumentNodeFactory::PITOKEN_GENERATE:
            {
	      bool okay = true;
              Template::Params args;
	      if (space != 0)
	      {
		TempString<> pStr (space + 1, valLen - cmdLen - 1);
		ParseTemplateArguments (pStr, args, false);
	      }
              if ((args.GetSize() < 3) || (args.GetSize() > 4))
              {
                okay = false;
	        Report (syntaxErrorSeverity, node,
		  "%s expects 3 or 4 arguments, got %zu",
		  CS::Quote::Single ("Generate"), args.GetSize());
              }
              if (okay)
              {
                state->generateVar = args[0];

                int start, end, step;
                char dummy;
                if (sscanf (args[1], "%d%c", &start, &dummy) != 1)
                {
	          Report (syntaxErrorSeverity, node,
		    "Argument %s is not an integer", CS::Quote::Single (args[1].GetData()));
                  okay = false;
                }
                if (okay && sscanf (args[2], "%d%c", &end, &dummy) != 1)
                {
	          Report (syntaxErrorSeverity, node,
		    "Argument %s is not an integer", CS::Quote::Single (args[2].GetData()));
                  okay = false;
                }
                if (okay)
                {
                  if (args.GetSize() == 4)
                  {
                    if (sscanf (args[3], "%d%c", &step, &dummy) != 1)
                    {
	              Report (syntaxErrorSeverity, node,
		        "Argument %s is not an integer", CS::Quote::Single (args[3].GetData()));
                      okay = false;
                    }
                  }
                  else
                  {
                    step = (end < start) ? -1 : 1;
                  }
                }
                if (okay)
                {
                  state->generateActive = true;
		              state->generateNestLevel = 1;
                  if (((start > end) && (step >= 0))
                    || ((end >= start) && (step <= 0)))
                  {
	                  Report (syntaxErrorSeverity, node,
		                  "Can't reach end value %d starting from %d with step %d", 
                      end, start, step);
                    state->generateValid = false;
                  }
                  else
                  {
                    state->generateValid = true;
                    state->generateStart = start;
                    state->generateEnd = end;
                    state->generateStep = step;
                    state->templ = Template();
                  }
                }
              }
	      handled = true;
            }
            break;
	  case csWrappedDocumentNodeFactory::PITOKEN_ENDGENERATE:
	    {
	      Report (syntaxErrorSeverity, node,
		"%s without %s",
		CS::Quote::Single ("Endgenerate"),
		CS::Quote::Single ("Generate"));
              // ProcessTemplate() would've handled it otherwise
	    }
	    break;
	  case csWrappedDocumentNodeFactory::PITOKEN_DEFINE:
            {
              TempString<> args (valStart + cmdLen, valLen - cmdLen);
              args.LTrim();
              ProcessDefine (state, node, args);
	      handled = true;
            }
	    break;
	  case csWrappedDocumentNodeFactory::PITOKEN_UNDEF:
            {
              TempString<> args (valStart + cmdLen, valLen - cmdLen);
              args.LTrim();
              ProcessUndef (state, node, args);
	      handled = true;
            }
	    break;
	  case csWrappedDocumentNodeFactory::PITOKEN_STATIC_IFDEF:
	  case csWrappedDocumentNodeFactory::PITOKEN_STATIC_IFNDEF:
            {
              TempString<> args (valStart + cmdLen, valLen - cmdLen);
              args.LTrim();
              ProcessStaticIfDef (state, node, args,
                tokenID == csWrappedDocumentNodeFactory::PITOKEN_STATIC_IFNDEF);
	      handled = true;
            }
            break;
          case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ELSIFDEF:
          case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ELSIFNDEF:
          case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ELSE:
          case csWrappedDocumentNodeFactory::PITOKEN_STATIC_ENDIF:
            {
	      Report (syntaxErrorSeverity, node,
		"%s without %s",
		CS::Quote::Single (shared->pitokens.Request (tokenID)),
		CS::Quote::Single ("SIfDef"));
              // ProcessStaticIf() would've handled it otherwise
	      handled = true;
            }
            break;
	  default:
	    {
	      Template::Params params;
	      if (space != 0)
	      {
		TempString<> pStr (space + 1, valLen - cmdLen - 1);
		ParseTemplateArguments (pStr, params, false);
	      }
	      if (InvokeTemplate (tokenStr, node, state, params))
	      {
            handled = true;
	      }
	      // If it's neither a template nor a recognized command, pass through
	    }
	}
      }
    }
  }
  if (!handled)
  {
    csRef<iDocumentNode> newWrapper;
    newWrapper.AttachNew (new csWrappedDocumentNode (this,
      node, shared, globalState));
    currentWrapper.Push (newWrapper);
  }
}
Beispiel #3
0
void CXMLparser::ProcessAttributes (CXMLelement & node)
  {
CAttribute * pAttribute;
CString strName;
CString strValue;

  while (m_xmlBuff [m_xmlPos] != '>')
    {
    // look for "empty element" terminator: />
    if (m_xmlBuff [m_xmlPos] == '/' && m_xmlBuff [m_xmlPos + 1] == '>')
      {
      node.bEmpty = true;
      m_xmlPos++; // skip '/' symbol
      break;
      }

    // look for terminator ?> at end of <?xml tag
    if (m_xmlBuff [m_xmlPos] == '?' && 
        m_xmlBuff [m_xmlPos + 1] == '>' &&
        node.strName [0] == '?'
        )
      {
      node.bEmpty = true;
      m_xmlPos++; // skip '?' symbol
      break;
      }

    // shouldn't have end-of-file before the >
    if (m_xmlBuff [m_xmlPos] == 0)
      ThrowErrorException ("Unexpected end-of-file inside element definition for %s",
                            (LPCTSTR) node.strName);

    // we really should have a name now ...

    strName = GetName ("Attribute");

    // already there? error
    if (node.AttributeMap.Lookup (strName, pAttribute))
      ThrowErrorException ("Duplicate attribute name '%s'",
                            (LPCTSTR) strName);

    // in case spaces before next thing
    SkipSpaces ();

    if (m_xmlBuff [m_xmlPos] != '=')
      ThrowErrorException ("Attribute name '%s' not followed by '='",
                            (LPCTSTR) strName);

    m_xmlPos++;    // skip the = sign

    int iLine =  m_xmlLine; // line that = sign is on

    strValue = GetValue ("attribute", strName);

    pAttribute = new CAttribute;

    if (!pAttribute)
      ThrowErrorException ("Could not allocate memory for XML parsing of attribute %s",
                            (LPCTSTR) strName);

    pAttribute->strName = strName;
    pAttribute->strValue = ReplaceEntities (strValue);
    pAttribute->iLine = iLine;

    // add to map
    node.AttributeMap.SetAt (strName, pAttribute);

    } // end of looking for attributes

  m_xmlPos++; // skip '>' symbol


  }   // end of CXMLparser::ProcessAttributes
Beispiel #4
0
void CXMLparser::AssembleContent (CXMLelement & node, 
                                    const UINT iFirstLine, 
                                    const UINT iNodeStart)
  {

/*
   work out content - it will be non-nested text belonging to this element
   eg. <a>xxx<b>yyy</b>zzz</a>
      "a" will have content xxxzzz
      "b" will have content yyy
   whitespace is preserved

   You can reassemble an entire element (including nested ones) by
   concatenating the contents of its children.
  
   For cross-platform consistency, carriage returns are dropped,
    and linefeeds become carriage-return/linefeed

  */

int iContentLen = m_xmlPos - iNodeStart;

int iLines = m_xmlLine - iFirstLine;    // lines of content
const char * pi = &m_xmlBuff [iNodeStart];    // copy from
const char * pl = &m_xmlBuff [m_xmlPos];      // limit of copy
char * po = node.strContent.GetBuffer (iContentLen + 1 + iLines); // copy to
int iDepth = 0;
bool bInside = false;
char cQuote = ' ';

  while (pi < pl)   // copy, dropping nested elements
    {

    // they might have <blah value=">">
    // so we have to skip special characters inside quotes

    if (bInside && (*pi == '\'' || *pi == '\"'))
      {
      cQuote = *pi;   // for terminator
      pi++;
      while (pi < pl && *pi != cQuote)
        pi++;
      pi++;  // skip terminating quote
      continue;   // back to start of loop
      } // end of quotes inside a definition

    // <![CDATA[  is special - just copy contents

    if (pi [0] == '<' &&
        pi [1] == '!' &&
        pi [2] == '[' &&
        pi [3] == 'C' &&
        pi [4] == 'D' &&
        pi [5] == 'A' &&
        pi [6] == 'T' &&
        pi [7] == 'A' &&
        pi [8] == '[')
      {

      pi += 9;  // skip <![CDATA[

      // this shouldn't happen
      if (bInside)
        ThrowErrorException ("Unexpected '<![CDATA[' inside element definition");

      // should be terminated as we checked earlier, but may as well check again
      while (pi < pl &&
             (pi [0] != ']' ||
              pi [1] != ']' ||
              pi [2] != '>'))
        {
       // copy if not nested, and not inside an element definition
       //  -- omit carriage returns
       if (iDepth == 0 && 
           *pi != '\r')
         {
         // make linefeeds into carriage return/linefeed
         if (*pi == '\n')
           *po++ = '\r';
         // special treatment for ampersands, so they don't get converted
         // into entities ...
         if (*pi == '&')
           *po++ = '\x01';
         else
          *po++ = *pi;    // copy it
         }
        pi++;
        }  // end of inside <![CDATA[

      pi += 3;  // skip ]]>
      continue; // back to start of loop

      } // end of <![CDATA[ section

    if (*pi == '<')   // going into an element
      {
      bInside = true;
      if (pi [1] == '/')   // </tag> drops a level
        {
        iDepth--;
       if (iDepth < 0)
         iDepth = 0;    // cannot have negative depth
        }
      else
        if (pi [1] != '!' && pi [1] != '?')  // excepting special ones
          iDepth++;           // <tag> goes up a level
      }

   // copy if not nested, and not inside an element definition
   //  -- omit carriage returns
   if (iDepth == 0 && 
      !bInside && 
      *pi != '\r')
     {
     // make linefeeds into carriage return/linefeed
     if (*pi == '\n')
       *po++ = '\r';
     *po++ = *pi;    // copy if not inside an element
     }
    
    // leaving an element (only occurs 'inside' a <... sequence )
   if (bInside && pi [0] == '/' && pi [1] == '>') 
     {
     iDepth--;  // cancel level gain - this tag is empty
     if (iDepth < 0)
       iDepth = 0;    // cannot have negative depth
     }
    else
      if (*pi == '>')   // leaving an element
        bInside = false;

    pi++; // onto next

    }
  
  *po = 0;  // terminating null
  node.strContent.ReleaseBuffer (-1);

  // get rid of entities (such as &lt;) in the content

  node.strContent = ReplaceEntities (node.strContent);

  // now, in case we had <![CDATA[ sections, replace 0x01 by &

  node.strContent.Replace ('\x01', '&');

  } // end of CXMLparser::AssembleContent