1) Fixed a mistaken assumption made by the XML error handling code in nsExpatTokenizer. It no longer treats the error location returned by expat as being relative to the current XML chunk being parsed. Instead, the error location is considered to be relative to the start of the XML file. The lengths of incoming XML chunks are added to a new member variable, mBytesParsed. When an error occurs, we subtract mBytesParsed from the error location returned by expat to give us the offset of the error in the XML chunk.

2) When nsWellFormedDTD sees an error token, it dumps the error to cerr and notifies the content sink about it.  This is a temporary solution.  The right behavior is for the browser to show the error in the content window which, currently, happens only for .XML documents.  XUL and RDF files use their own content sinks which do not implement error handling.  This needs to change so that code is shared among the XML, RDF, and XUL content sinks. I do not want to fix error handling by just cutting and pasting the error handling code from the XML content sink into the RDF and XUL content sinks.


git-svn-id: svn://10.0.0.236/trunk@26469 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
nisheeth%netscape.com 1999-04-06 08:17:03 +00:00
parent 54f021f686
commit 6eadea42c7
6 changed files with 68 additions and 14 deletions

View File

@ -132,6 +132,7 @@ void nsExpatTokenizer::SetupExpatCallbacks(void) {
*/
nsExpatTokenizer::nsExpatTokenizer() : nsHTMLTokenizer() {
NS_INIT_REFCNT();
mBytesParsed = 0;
mExpatParser = XML_ParserCreate(NULL);
gTokenRecycler=(CTokenRecycler*)GetTokenRecycler();
if (mExpatParser) {
@ -157,11 +158,11 @@ nsExpatTokenizer::~nsExpatTokenizer(){
*******************************************************************/
static void SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex,
void nsExpatTokenizer::SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex,
const char* aSourceBuffer, PRUint32 aLength)
{
/* Figure out the substring inside aSourceBuffer that contains the line on which the error
occurred. Copy the line into error->sourceLine */
occurred. Copy the line into aError->sourceLine */
PR_ASSERT(aByteIndex > 0 && aByteIndex < aLength);
char* start = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the start of the line */
char* end = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the end of the line */
@ -213,13 +214,14 @@ void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength)
{
CErrorToken* token= (CErrorToken *) gTokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
nsParserError *error = new nsParserError;
PRUint32 byteIndexRelativeToFile = 0;
error->code = XML_GetErrorCode(mExpatParser);
error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
error->colNumber = XML_GetCurrentColumnNumber(mExpatParser);
error->description = XML_ErrorString(error->code);
SetErrorContextInfo(error, (PRUint32) XML_GetCurrentByteIndex(mExpatParser), aBuffer, aLength);
error->description = XML_ErrorString(error->code);
byteIndexRelativeToFile = XML_GetCurrentByteIndex(mExpatParser);
SetErrorContextInfo(error, (byteIndexRelativeToFile - mBytesParsed), aBuffer, aLength);
token->SetError(error);
CToken* theToken = (CToken* )token;
@ -230,9 +232,10 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char *aBuffer, PRUint32 aLength)
nsresult result=NS_OK;
if (mExpatParser) {
PR_ASSERT(aLength == strlen(aBuffer));
if (!XML_Parse(mExpatParser, aBuffer, aLength, PR_FALSE)) {
if (!XML_Parse(mExpatParser, aBuffer, aLength, PR_FALSE)) {
PushXMLErrorToken(aBuffer, aLength);
}
}
mBytesParsed += aLength;
}
else {
result = NS_ERROR_FAILURE;

View File

@ -74,6 +74,8 @@ protected:
void SetupExpatCallbacks(void);
void PushXMLErrorToken(const char *aBuffer, PRUint32 aLength);
void SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex,
const char* aSourceBuffer, PRUint32 aLength);
/* The callback handlers that get called from the expat parser */
static void HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts);
@ -104,6 +106,7 @@ protected:
XML_Encoding *info);
XML_Parser mExpatParser;
PRUint32 mBytesParsed;
};
extern NS_HTMLPARS nsresult NS_Expat_Tokenizer(nsIDTD** aInstancePtrResult);

View File

@ -50,6 +50,7 @@
#include "nsSpecialSystemDirectory.h"
#include <ctype.h> // toupper()
#include "nsString.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
@ -516,6 +517,26 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken,nsIParser* aParser) {
{
// Propagate the error onto the content sink.
CErrorToken *errTok = (CErrorToken *)aToken;
// XXX Dump error to error output stream just in case the content
// sink is RDF or XUL and does not implement error handling. We need to factor
// code better among HTMLContentSink, XMLContentSink, RDFContentSink,
// and XULContentSink. Until that happens, instead of cutting and
// pasting error handling code for each content sink, I output an
// error to cerr here.
const nsParserError* error = errTok->GetError();
if (error) {
char* temp;
cerr << "XML Error in file '" << (temp = mFilename.ToNewCString()) << "', ";
delete [] temp;
cerr << "Line Number: " << error->lineNumber << ", ";
cerr << "Col Number: " << error->colNumber << ", ";
cerr << "Description: " << (temp = error->description.ToNewCString()) << "\n";
delete [] temp;
cerr << "Source Line: " << (temp = error->sourceLine.ToNewCString()) << "\n";
delete [] temp;
}
result = mSink->NotifyError(errTok->GetError());
}
break;

View File

@ -132,6 +132,7 @@ void nsExpatTokenizer::SetupExpatCallbacks(void) {
*/
nsExpatTokenizer::nsExpatTokenizer() : nsHTMLTokenizer() {
NS_INIT_REFCNT();
mBytesParsed = 0;
mExpatParser = XML_ParserCreate(NULL);
gTokenRecycler=(CTokenRecycler*)GetTokenRecycler();
if (mExpatParser) {
@ -157,11 +158,11 @@ nsExpatTokenizer::~nsExpatTokenizer(){
*******************************************************************/
static void SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex,
void nsExpatTokenizer::SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex,
const char* aSourceBuffer, PRUint32 aLength)
{
/* Figure out the substring inside aSourceBuffer that contains the line on which the error
occurred. Copy the line into error->sourceLine */
occurred. Copy the line into aError->sourceLine */
PR_ASSERT(aByteIndex > 0 && aByteIndex < aLength);
char* start = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the start of the line */
char* end = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the end of the line */
@ -213,13 +214,14 @@ void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength)
{
CErrorToken* token= (CErrorToken *) gTokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
nsParserError *error = new nsParserError;
PRUint32 byteIndexRelativeToFile = 0;
error->code = XML_GetErrorCode(mExpatParser);
error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
error->colNumber = XML_GetCurrentColumnNumber(mExpatParser);
error->description = XML_ErrorString(error->code);
SetErrorContextInfo(error, (PRUint32) XML_GetCurrentByteIndex(mExpatParser), aBuffer, aLength);
error->description = XML_ErrorString(error->code);
byteIndexRelativeToFile = XML_GetCurrentByteIndex(mExpatParser);
SetErrorContextInfo(error, (byteIndexRelativeToFile - mBytesParsed), aBuffer, aLength);
token->SetError(error);
CToken* theToken = (CToken* )token;
@ -230,9 +232,10 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char *aBuffer, PRUint32 aLength)
nsresult result=NS_OK;
if (mExpatParser) {
PR_ASSERT(aLength == strlen(aBuffer));
if (!XML_Parse(mExpatParser, aBuffer, aLength, PR_FALSE)) {
if (!XML_Parse(mExpatParser, aBuffer, aLength, PR_FALSE)) {
PushXMLErrorToken(aBuffer, aLength);
}
}
mBytesParsed += aLength;
}
else {
result = NS_ERROR_FAILURE;

View File

@ -74,6 +74,8 @@ protected:
void SetupExpatCallbacks(void);
void PushXMLErrorToken(const char *aBuffer, PRUint32 aLength);
void SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex,
const char* aSourceBuffer, PRUint32 aLength);
/* The callback handlers that get called from the expat parser */
static void HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts);
@ -104,6 +106,7 @@ protected:
XML_Encoding *info);
XML_Parser mExpatParser;
PRUint32 mBytesParsed;
};
extern NS_HTMLPARS nsresult NS_Expat_Tokenizer(nsIDTD** aInstancePtrResult);

View File

@ -50,6 +50,7 @@
#include "nsSpecialSystemDirectory.h"
#include <ctype.h> // toupper()
#include "nsString.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
@ -516,6 +517,26 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken,nsIParser* aParser) {
{
// Propagate the error onto the content sink.
CErrorToken *errTok = (CErrorToken *)aToken;
// XXX Dump error to error output stream just in case the content
// sink is RDF or XUL and does not implement error handling. We need to factor
// code better among HTMLContentSink, XMLContentSink, RDFContentSink,
// and XULContentSink. Until that happens, instead of cutting and
// pasting error handling code for each content sink, I output an
// error to cerr here.
const nsParserError* error = errTok->GetError();
if (error) {
char* temp;
cerr << "XML Error in file '" << (temp = mFilename.ToNewCString()) << "', ";
delete [] temp;
cerr << "Line Number: " << error->lineNumber << ", ";
cerr << "Col Number: " << error->colNumber << ", ";
cerr << "Description: " << (temp = error->description.ToNewCString()) << "\n";
delete [] temp;
cerr << "Source Line: " << (temp = error->sourceLine.ToNewCString()) << "\n";
delete [] temp;
}
result = mSink->NotifyError(errTok->GetError());
}
break;