зеркало из https://github.com/mozilla/gecko-dev.git
r=pollmann. Fix for bug 29395. XML error messages now show up in the content area for XML, RDF, and XUL files. Earlier, they would only show up for XML files.
- Generate tokens in the expat tokenizer to display an XML error message. - Process those tokens in the XML DTD - Add a SetStringValue() method to CToken that accepts an nsString parameter. - Removed code in the XML content sink's NotifyError() method to create error message content.
This commit is contained in:
Родитель
8d8fffcdaa
Коммит
bc23c89148
|
@ -868,125 +868,10 @@ nsXMLContentSink::AddLeaf(const nsIParserNode& aNode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsXMLContentSink::CreateErrorText(const nsParserError* aError, nsString& aErrorString)
|
||||
{
|
||||
nsString errorText("XML Parsing Error: ");
|
||||
|
||||
if (aError) {
|
||||
errorText.Append(aError->description);
|
||||
errorText.Append("\nLine Number ");
|
||||
errorText.Append(aError->lineNumber, 10);
|
||||
errorText.Append(", Column ");
|
||||
errorText.Append(aError->colNumber, 10);
|
||||
errorText.Append(":");
|
||||
}
|
||||
|
||||
aErrorString = errorText;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsXMLContentSink::CreateSourceText(const nsParserError* aError, nsString& aSourceString)
|
||||
{
|
||||
nsString sourceText;
|
||||
PRInt32 errorPosition = aError->colNumber;
|
||||
|
||||
sourceText.Append(aError->sourceLine);
|
||||
sourceText.Append("\n");
|
||||
for (int i = 0; i < errorPosition; i++)
|
||||
sourceText.Append("-");
|
||||
sourceText.Append("^");
|
||||
|
||||
aSourceString = sourceText;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void SetTextStringOnTextNode(const nsString& aTextString, nsIContent* aTextNode)
|
||||
{
|
||||
nsITextContent* text = nsnull;
|
||||
PRUnichar *tempUnicode = aTextString.ToNewUnicode();
|
||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);
|
||||
|
||||
aTextNode->QueryInterface(kITextContentIID, (void**) &text);
|
||||
text->SetText(tempUnicode, aTextString.Length(), PR_FALSE);
|
||||
delete [] tempUnicode;
|
||||
NS_RELEASE(text);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We create the following XML snippet programmatically and
|
||||
* insert it into the content model:
|
||||
*
|
||||
* <ParserError>
|
||||
* XML Error: "contents of aError->description"
|
||||
* Line Number: "contents of aError->lineNumber"
|
||||
* <SourceText>
|
||||
* "Contents of aError->sourceLine"
|
||||
* "^ pointing at the error location"
|
||||
* </SourceText>
|
||||
* </ParserError>
|
||||
*
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsXMLContentSink::NotifyError(const nsParserError* aError)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsAutoString parserErrorTag = "parsererror";
|
||||
nsAutoString sourceTextTag = "sourcetext";
|
||||
nsString errorText;
|
||||
nsString sourceText;
|
||||
nsIHTMLContent* errorContainerNode = nsnull;
|
||||
nsIHTMLContent* sourceContainerNode = nsnull;
|
||||
nsIContent* errorTextNode = nsnull;
|
||||
nsIContent* sourceTextNode = nsnull;
|
||||
|
||||
/* Create container and text content nodes */
|
||||
result = NS_CreateHTMLElement(&errorContainerNode, parserErrorTag); // XXX these should NOT be in the HTML namespace
|
||||
if (NS_OK == result) {
|
||||
result = NS_NewTextNode(&errorTextNode);
|
||||
if (NS_OK == result) {
|
||||
result = NS_CreateHTMLElement(&sourceContainerNode, sourceTextTag);
|
||||
if (NS_OK == result) {
|
||||
result = NS_NewTextNode(&sourceTextNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the error text string and source text string
|
||||
and set the text strings into the text nodes. */
|
||||
result = CreateErrorText(aError, errorText);
|
||||
if (NS_OK == result) {
|
||||
SetTextStringOnTextNode(errorText, errorTextNode);
|
||||
}
|
||||
|
||||
result = CreateSourceText(aError, sourceText);
|
||||
if (NS_OK == result) {
|
||||
SetTextStringOnTextNode(sourceText, sourceTextNode);
|
||||
}
|
||||
|
||||
/* Hook the content nodes up to the document and to each other */
|
||||
if (NS_OK == result) {
|
||||
errorContainerNode->SetDocument(mDocument, PR_FALSE);
|
||||
errorTextNode->SetDocument(mDocument, PR_FALSE);
|
||||
sourceContainerNode->SetDocument(mDocument, PR_FALSE);
|
||||
sourceTextNode->SetDocument(mDocument, PR_FALSE);
|
||||
|
||||
if (nsnull == mDocElement) {
|
||||
mDocElement = errorContainerNode;
|
||||
NS_ADDREF(mDocElement);
|
||||
mDocument->SetRootContent(mDocElement);
|
||||
}
|
||||
else {
|
||||
mDocElement->AppendChildTo(errorContainerNode, PR_FALSE);
|
||||
}
|
||||
errorContainerNode->AppendChildTo(errorTextNode, PR_FALSE);
|
||||
errorContainerNode->AppendChildTo(sourceContainerNode, PR_FALSE);
|
||||
sourceContainerNode->AppendChildTo(sourceTextNode, PR_FALSE);
|
||||
}
|
||||
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIXMLContentSink
|
||||
|
|
|
@ -158,8 +158,6 @@ protected:
|
|||
void StartLayoutProcess();
|
||||
|
||||
nsresult AddText(const nsString& aString);
|
||||
nsresult CreateErrorText(const nsParserError* aError, nsString& aErrorString);
|
||||
nsresult CreateSourceText(const nsParserError* aError, nsString& aSourceString);
|
||||
|
||||
static void
|
||||
GetElementFactory(PRInt32 aNameSpaceID, nsIElementFactory** aResult);
|
||||
|
|
|
@ -61,6 +61,7 @@ static NS_DEFINE_IID(kClassIID, NS_EXPATTOKENIZER_IID);
|
|||
static const char* kDocTypeDeclPrefix = "<!DOCTYPE";
|
||||
static const char* kChromeProtocol = "chrome";
|
||||
static const char* kDTDDirectory = "dtd/";
|
||||
static const char kHTMLNameSpaceURI[] = "http://www.w3.org/TR/REC-html40";
|
||||
|
||||
const nsIID&
|
||||
nsExpatTokenizer::GetIID()
|
||||
|
@ -286,17 +287,112 @@ void nsExpatTokenizer::GetLine(const char* aSourceBuffer, PRUint32 aLength,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static nsresult
|
||||
CreateErrorText(const nsParserError* aError, nsString& aErrorString)
|
||||
{
|
||||
aErrorString = "XML Parsing Error: ";
|
||||
|
||||
if (aError) {
|
||||
aErrorString.Append(aError->description);
|
||||
aErrorString.Append("\nLine Number ");
|
||||
aErrorString.Append(aError->lineNumber, 10);
|
||||
aErrorString.Append(", Column ");
|
||||
aErrorString.Append(aError->colNumber, 10);
|
||||
aErrorString.Append(":");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
CreateSourceText(const nsParserError* aError, nsString& aSourceString)
|
||||
{
|
||||
PRInt32 errorPosition = aError->colNumber;
|
||||
|
||||
aSourceString.Append(aError->sourceLine);
|
||||
aSourceString.Append("\n");
|
||||
for (int i = 0; i < errorPosition; i++)
|
||||
aSourceString.Append("-");
|
||||
aSourceString.Append("^");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Create and add the tokens in the following order to display the error:
|
||||
ParserError start token
|
||||
Text token containing error message
|
||||
SourceText start token
|
||||
Text token containing source text
|
||||
SourceText end token
|
||||
ParserError end token
|
||||
*/
|
||||
nsresult
|
||||
nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
CToken* newToken = mState->tokenRecycler->CreateTokenOfType(eToken_start, eHTMLTag_parsererror);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
CAttributeToken* attrToken = (CAttributeToken*)
|
||||
mState->tokenRecycler->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown);
|
||||
nsString& key = attrToken->GetKey();
|
||||
key.Assign("xmlns");
|
||||
attrToken->SetStringValue(kHTMLNameSpaceURI);
|
||||
newToken->SetAttributeCount(1);
|
||||
newToken = (CToken*) attrToken;
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
nsAutoString textStr;
|
||||
CreateErrorText(aError, textStr);
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_text, eHTMLTag_unknown);
|
||||
newToken->SetStringValue(textStr);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_start, eHTMLTag_sourcetext);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
textStr.Truncate();
|
||||
CreateSourceText(aError, textStr);
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_text, eHTMLTag_unknown);
|
||||
newToken->SetStringValue(textStr);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_end, eHTMLTag_sourcetext);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_end, eHTMLTag_parsererror);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called immediately after an error has occurred in expat. Creates
|
||||
* an error token and pushes it onto the token queue.
|
||||
* tokens to display the error and an error token to the token stream.
|
||||
*
|
||||
* The error tokens will end up creating the following content model
|
||||
* in the content sink:
|
||||
*
|
||||
* <ParserError>
|
||||
* XML Error: "contents of aError->description"
|
||||
* Line Number: "contents of aError->lineNumber"
|
||||
* <SourceText>
|
||||
* "Contents of aError->sourceLine"
|
||||
* "^ pointing at the error location"
|
||||
* </SourceText>
|
||||
* </ParserError>
|
||||
*
|
||||
*/
|
||||
void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal)
|
||||
nsresult
|
||||
nsExpatTokenizer::PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal)
|
||||
{
|
||||
CErrorToken* token= (CErrorToken *) mState->tokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
|
||||
CErrorToken* errorToken= (CErrorToken *) mState->tokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
|
||||
nsParserError *error = new nsParserError;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if(error){
|
||||
if (error && errorToken) {
|
||||
/* Fill in the values of the error token */
|
||||
error->code = XML_GetErrorCode(mExpatParser);
|
||||
error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
|
||||
error->colNumber = XML_GetCurrentColumnNumber(mExpatParser);
|
||||
|
@ -310,11 +406,18 @@ void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength,
|
|||
error->sourceLine.Append(mLastLine);
|
||||
}
|
||||
|
||||
token->SetError(error);
|
||||
errorToken->SetError(error);
|
||||
|
||||
CToken* theToken = (CToken* )token;
|
||||
AddToken(theToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
/* Add the error token */
|
||||
CToken* newToken = (CToken*) errorToken;
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
/* Add the error message tokens */
|
||||
AddErrorMessageTokens(error);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsExpatTokenizer::ParseXMLBuffer(const char* aBuffer, PRUint32 aLength, PRBool aIsFinal)
|
||||
|
@ -326,7 +429,7 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char* aBuffer, PRUint32 aLength,
|
|||
nsCOMPtr<nsExpatTokenizer> me=this;
|
||||
|
||||
if (!XML_Parse(mExpatParser, aBuffer, aLength, aIsFinal)) {
|
||||
PushXMLErrorToken(aBuffer, aLength, aIsFinal);
|
||||
PushXMLErrorTokens(aBuffer, aLength, aIsFinal);
|
||||
result=NS_ERROR_HTMLPARSER_STOPPARSING;
|
||||
}
|
||||
else if (aBuffer && aLength) {
|
||||
|
|
|
@ -94,7 +94,9 @@ protected:
|
|||
void SetupExpatParser(void);
|
||||
|
||||
// Propagate XML errors to the content sink
|
||||
void PushXMLErrorToken(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal);
|
||||
nsresult PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal);
|
||||
nsresult AddErrorMessageTokens(nsParserError* aError);
|
||||
|
||||
void GetLine(const char* aSourceBuffer, PRUint32 aLength,
|
||||
PRUint32 aByteIndex, nsString& aLine);
|
||||
|
||||
|
|
|
@ -167,6 +167,14 @@ void CToken::SetStringValue(const char* name){
|
|||
mTextValue=name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter method for the string value of this token
|
||||
*/
|
||||
void CToken::SetStringValue(nsString& aStr)
|
||||
{
|
||||
mTextValue = aStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves the value of this internal string.
|
||||
*
|
||||
|
|
|
@ -126,6 +126,11 @@ class CToken {
|
|||
*/
|
||||
virtual void SetStringValue(const char* name);
|
||||
|
||||
/**
|
||||
* Setter method for the string value of this token
|
||||
*/
|
||||
virtual void SetStringValue(nsString& aStr);
|
||||
|
||||
/**
|
||||
* Retrieve string value of the token as a c-string
|
||||
* @update gess5/11/98
|
||||
|
|
|
@ -474,8 +474,9 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken,nsIParser* aParser) {
|
|||
eHTMLTokenTypes theType= (eHTMLTokenTypes)theToken->GetTokenType();
|
||||
|
||||
if(mDTDState==NS_ERROR_HTMLPARSER_STOPPARSING) {
|
||||
//Report only errors to the sink.
|
||||
if(theType!=eToken_error) return result;
|
||||
// Report only errors to the sink.
|
||||
if(theType != eToken_error)
|
||||
return result;
|
||||
}
|
||||
|
||||
mParser=(nsParser*)aParser;
|
||||
|
@ -658,31 +659,55 @@ nsresult CWellFormedDTD::HandleEndToken(CToken* aToken) {
|
|||
|
||||
nsresult CWellFormedDTD::HandleErrorToken(CToken* aToken) {
|
||||
NS_PRECONDITION(0!=aToken,"null token");
|
||||
nsresult result=NS_OK;
|
||||
|
||||
nsresult result=NS_OK;
|
||||
// Cycle through the remaining tokens in the token stream and handle them
|
||||
// These tokens were added so that content objects for the error message
|
||||
// are generated by the content sink
|
||||
while (PR_TRUE) {
|
||||
CToken* token = mTokenizer->PopToken();
|
||||
if(token) {
|
||||
eHTMLTokenTypes type = (eHTMLTokenTypes) token->GetTokenType();
|
||||
switch(type) {
|
||||
case eToken_newline:
|
||||
mLineNumber++; //now fall through
|
||||
case eToken_whitespace:
|
||||
case eToken_text:
|
||||
HandleLeafToken(token);
|
||||
break;
|
||||
case eToken_start:
|
||||
HandleStartToken(token);
|
||||
break;
|
||||
case eToken_end:
|
||||
HandleEndToken(token);
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// 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();
|
||||
result=(mSink)? mSink->NotifyError(error):NS_OK;
|
||||
|
||||
// Output the error to the console
|
||||
if (error) {
|
||||
char* temp;
|
||||
cerr << "XML Error in file '" << (temp = mFilename.ToNewCString()) << "', ";
|
||||
cout << "XML Error in file '" << (temp = mFilename.ToNewCString()) << "', ";
|
||||
Recycle(temp);
|
||||
cerr << "Line Number: " << error->lineNumber << ", ";
|
||||
cerr << "Col Number: " << error->colNumber << ", ";
|
||||
cerr << "Description: " << (temp = error->description.ToNewCString()) << "\n";
|
||||
cout << "Line Number: " << error->lineNumber << ", ";
|
||||
cout << "Col Number: " << error->colNumber << ", ";
|
||||
cout << "Description: " << (temp = error->description.ToNewCString()) << "\n";
|
||||
Recycle(temp);
|
||||
cerr << "Source Line: " << (temp = error->sourceLine.ToNewCString()) << "\n";
|
||||
cout << "Source Line: " << (temp = error->sourceLine.ToNewCString()) << "\n";
|
||||
Recycle(temp);
|
||||
}
|
||||
result=(mSink)? mSink->NotifyError(errTok->GetError()):NS_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -868,125 +868,10 @@ nsXMLContentSink::AddLeaf(const nsIParserNode& aNode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsXMLContentSink::CreateErrorText(const nsParserError* aError, nsString& aErrorString)
|
||||
{
|
||||
nsString errorText("XML Parsing Error: ");
|
||||
|
||||
if (aError) {
|
||||
errorText.Append(aError->description);
|
||||
errorText.Append("\nLine Number ");
|
||||
errorText.Append(aError->lineNumber, 10);
|
||||
errorText.Append(", Column ");
|
||||
errorText.Append(aError->colNumber, 10);
|
||||
errorText.Append(":");
|
||||
}
|
||||
|
||||
aErrorString = errorText;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsXMLContentSink::CreateSourceText(const nsParserError* aError, nsString& aSourceString)
|
||||
{
|
||||
nsString sourceText;
|
||||
PRInt32 errorPosition = aError->colNumber;
|
||||
|
||||
sourceText.Append(aError->sourceLine);
|
||||
sourceText.Append("\n");
|
||||
for (int i = 0; i < errorPosition; i++)
|
||||
sourceText.Append("-");
|
||||
sourceText.Append("^");
|
||||
|
||||
aSourceString = sourceText;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void SetTextStringOnTextNode(const nsString& aTextString, nsIContent* aTextNode)
|
||||
{
|
||||
nsITextContent* text = nsnull;
|
||||
PRUnichar *tempUnicode = aTextString.ToNewUnicode();
|
||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);
|
||||
|
||||
aTextNode->QueryInterface(kITextContentIID, (void**) &text);
|
||||
text->SetText(tempUnicode, aTextString.Length(), PR_FALSE);
|
||||
delete [] tempUnicode;
|
||||
NS_RELEASE(text);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We create the following XML snippet programmatically and
|
||||
* insert it into the content model:
|
||||
*
|
||||
* <ParserError>
|
||||
* XML Error: "contents of aError->description"
|
||||
* Line Number: "contents of aError->lineNumber"
|
||||
* <SourceText>
|
||||
* "Contents of aError->sourceLine"
|
||||
* "^ pointing at the error location"
|
||||
* </SourceText>
|
||||
* </ParserError>
|
||||
*
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsXMLContentSink::NotifyError(const nsParserError* aError)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsAutoString parserErrorTag = "parsererror";
|
||||
nsAutoString sourceTextTag = "sourcetext";
|
||||
nsString errorText;
|
||||
nsString sourceText;
|
||||
nsIHTMLContent* errorContainerNode = nsnull;
|
||||
nsIHTMLContent* sourceContainerNode = nsnull;
|
||||
nsIContent* errorTextNode = nsnull;
|
||||
nsIContent* sourceTextNode = nsnull;
|
||||
|
||||
/* Create container and text content nodes */
|
||||
result = NS_CreateHTMLElement(&errorContainerNode, parserErrorTag); // XXX these should NOT be in the HTML namespace
|
||||
if (NS_OK == result) {
|
||||
result = NS_NewTextNode(&errorTextNode);
|
||||
if (NS_OK == result) {
|
||||
result = NS_CreateHTMLElement(&sourceContainerNode, sourceTextTag);
|
||||
if (NS_OK == result) {
|
||||
result = NS_NewTextNode(&sourceTextNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the error text string and source text string
|
||||
and set the text strings into the text nodes. */
|
||||
result = CreateErrorText(aError, errorText);
|
||||
if (NS_OK == result) {
|
||||
SetTextStringOnTextNode(errorText, errorTextNode);
|
||||
}
|
||||
|
||||
result = CreateSourceText(aError, sourceText);
|
||||
if (NS_OK == result) {
|
||||
SetTextStringOnTextNode(sourceText, sourceTextNode);
|
||||
}
|
||||
|
||||
/* Hook the content nodes up to the document and to each other */
|
||||
if (NS_OK == result) {
|
||||
errorContainerNode->SetDocument(mDocument, PR_FALSE);
|
||||
errorTextNode->SetDocument(mDocument, PR_FALSE);
|
||||
sourceContainerNode->SetDocument(mDocument, PR_FALSE);
|
||||
sourceTextNode->SetDocument(mDocument, PR_FALSE);
|
||||
|
||||
if (nsnull == mDocElement) {
|
||||
mDocElement = errorContainerNode;
|
||||
NS_ADDREF(mDocElement);
|
||||
mDocument->SetRootContent(mDocElement);
|
||||
}
|
||||
else {
|
||||
mDocElement->AppendChildTo(errorContainerNode, PR_FALSE);
|
||||
}
|
||||
errorContainerNode->AppendChildTo(errorTextNode, PR_FALSE);
|
||||
errorContainerNode->AppendChildTo(sourceContainerNode, PR_FALSE);
|
||||
sourceContainerNode->AppendChildTo(sourceTextNode, PR_FALSE);
|
||||
}
|
||||
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIXMLContentSink
|
||||
|
|
|
@ -158,8 +158,6 @@ protected:
|
|||
void StartLayoutProcess();
|
||||
|
||||
nsresult AddText(const nsString& aString);
|
||||
nsresult CreateErrorText(const nsParserError* aError, nsString& aErrorString);
|
||||
nsresult CreateSourceText(const nsParserError* aError, nsString& aSourceString);
|
||||
|
||||
static void
|
||||
GetElementFactory(PRInt32 aNameSpaceID, nsIElementFactory** aResult);
|
||||
|
|
|
@ -61,6 +61,7 @@ static NS_DEFINE_IID(kClassIID, NS_EXPATTOKENIZER_IID);
|
|||
static const char* kDocTypeDeclPrefix = "<!DOCTYPE";
|
||||
static const char* kChromeProtocol = "chrome";
|
||||
static const char* kDTDDirectory = "dtd/";
|
||||
static const char kHTMLNameSpaceURI[] = "http://www.w3.org/TR/REC-html40";
|
||||
|
||||
const nsIID&
|
||||
nsExpatTokenizer::GetIID()
|
||||
|
@ -286,17 +287,112 @@ void nsExpatTokenizer::GetLine(const char* aSourceBuffer, PRUint32 aLength,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static nsresult
|
||||
CreateErrorText(const nsParserError* aError, nsString& aErrorString)
|
||||
{
|
||||
aErrorString = "XML Parsing Error: ";
|
||||
|
||||
if (aError) {
|
||||
aErrorString.Append(aError->description);
|
||||
aErrorString.Append("\nLine Number ");
|
||||
aErrorString.Append(aError->lineNumber, 10);
|
||||
aErrorString.Append(", Column ");
|
||||
aErrorString.Append(aError->colNumber, 10);
|
||||
aErrorString.Append(":");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
CreateSourceText(const nsParserError* aError, nsString& aSourceString)
|
||||
{
|
||||
PRInt32 errorPosition = aError->colNumber;
|
||||
|
||||
aSourceString.Append(aError->sourceLine);
|
||||
aSourceString.Append("\n");
|
||||
for (int i = 0; i < errorPosition; i++)
|
||||
aSourceString.Append("-");
|
||||
aSourceString.Append("^");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Create and add the tokens in the following order to display the error:
|
||||
ParserError start token
|
||||
Text token containing error message
|
||||
SourceText start token
|
||||
Text token containing source text
|
||||
SourceText end token
|
||||
ParserError end token
|
||||
*/
|
||||
nsresult
|
||||
nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
CToken* newToken = mState->tokenRecycler->CreateTokenOfType(eToken_start, eHTMLTag_parsererror);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
CAttributeToken* attrToken = (CAttributeToken*)
|
||||
mState->tokenRecycler->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown);
|
||||
nsString& key = attrToken->GetKey();
|
||||
key.Assign("xmlns");
|
||||
attrToken->SetStringValue(kHTMLNameSpaceURI);
|
||||
newToken->SetAttributeCount(1);
|
||||
newToken = (CToken*) attrToken;
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
nsAutoString textStr;
|
||||
CreateErrorText(aError, textStr);
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_text, eHTMLTag_unknown);
|
||||
newToken->SetStringValue(textStr);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_start, eHTMLTag_sourcetext);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
textStr.Truncate();
|
||||
CreateSourceText(aError, textStr);
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_text, eHTMLTag_unknown);
|
||||
newToken->SetStringValue(textStr);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_end, eHTMLTag_sourcetext);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
newToken = mState->tokenRecycler->CreateTokenOfType(eToken_end, eHTMLTag_parsererror);
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called immediately after an error has occurred in expat. Creates
|
||||
* an error token and pushes it onto the token queue.
|
||||
* tokens to display the error and an error token to the token stream.
|
||||
*
|
||||
* The error tokens will end up creating the following content model
|
||||
* in the content sink:
|
||||
*
|
||||
* <ParserError>
|
||||
* XML Error: "contents of aError->description"
|
||||
* Line Number: "contents of aError->lineNumber"
|
||||
* <SourceText>
|
||||
* "Contents of aError->sourceLine"
|
||||
* "^ pointing at the error location"
|
||||
* </SourceText>
|
||||
* </ParserError>
|
||||
*
|
||||
*/
|
||||
void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal)
|
||||
nsresult
|
||||
nsExpatTokenizer::PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal)
|
||||
{
|
||||
CErrorToken* token= (CErrorToken *) mState->tokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
|
||||
CErrorToken* errorToken= (CErrorToken *) mState->tokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
|
||||
nsParserError *error = new nsParserError;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if(error){
|
||||
if (error && errorToken) {
|
||||
/* Fill in the values of the error token */
|
||||
error->code = XML_GetErrorCode(mExpatParser);
|
||||
error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
|
||||
error->colNumber = XML_GetCurrentColumnNumber(mExpatParser);
|
||||
|
@ -310,11 +406,18 @@ void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength,
|
|||
error->sourceLine.Append(mLastLine);
|
||||
}
|
||||
|
||||
token->SetError(error);
|
||||
errorToken->SetError(error);
|
||||
|
||||
CToken* theToken = (CToken* )token;
|
||||
AddToken(theToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
/* Add the error token */
|
||||
CToken* newToken = (CToken*) errorToken;
|
||||
AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenRecycler);
|
||||
|
||||
/* Add the error message tokens */
|
||||
AddErrorMessageTokens(error);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsExpatTokenizer::ParseXMLBuffer(const char* aBuffer, PRUint32 aLength, PRBool aIsFinal)
|
||||
|
@ -326,7 +429,7 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char* aBuffer, PRUint32 aLength,
|
|||
nsCOMPtr<nsExpatTokenizer> me=this;
|
||||
|
||||
if (!XML_Parse(mExpatParser, aBuffer, aLength, aIsFinal)) {
|
||||
PushXMLErrorToken(aBuffer, aLength, aIsFinal);
|
||||
PushXMLErrorTokens(aBuffer, aLength, aIsFinal);
|
||||
result=NS_ERROR_HTMLPARSER_STOPPARSING;
|
||||
}
|
||||
else if (aBuffer && aLength) {
|
||||
|
|
|
@ -94,7 +94,9 @@ protected:
|
|||
void SetupExpatParser(void);
|
||||
|
||||
// Propagate XML errors to the content sink
|
||||
void PushXMLErrorToken(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal);
|
||||
nsresult PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal);
|
||||
nsresult AddErrorMessageTokens(nsParserError* aError);
|
||||
|
||||
void GetLine(const char* aSourceBuffer, PRUint32 aLength,
|
||||
PRUint32 aByteIndex, nsString& aLine);
|
||||
|
||||
|
|
|
@ -167,6 +167,14 @@ void CToken::SetStringValue(const char* name){
|
|||
mTextValue=name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter method for the string value of this token
|
||||
*/
|
||||
void CToken::SetStringValue(nsString& aStr)
|
||||
{
|
||||
mTextValue = aStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves the value of this internal string.
|
||||
*
|
||||
|
|
|
@ -126,6 +126,11 @@ class CToken {
|
|||
*/
|
||||
virtual void SetStringValue(const char* name);
|
||||
|
||||
/**
|
||||
* Setter method for the string value of this token
|
||||
*/
|
||||
virtual void SetStringValue(nsString& aStr);
|
||||
|
||||
/**
|
||||
* Retrieve string value of the token as a c-string
|
||||
* @update gess5/11/98
|
||||
|
|
|
@ -474,8 +474,9 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken,nsIParser* aParser) {
|
|||
eHTMLTokenTypes theType= (eHTMLTokenTypes)theToken->GetTokenType();
|
||||
|
||||
if(mDTDState==NS_ERROR_HTMLPARSER_STOPPARSING) {
|
||||
//Report only errors to the sink.
|
||||
if(theType!=eToken_error) return result;
|
||||
// Report only errors to the sink.
|
||||
if(theType != eToken_error)
|
||||
return result;
|
||||
}
|
||||
|
||||
mParser=(nsParser*)aParser;
|
||||
|
@ -658,31 +659,55 @@ nsresult CWellFormedDTD::HandleEndToken(CToken* aToken) {
|
|||
|
||||
nsresult CWellFormedDTD::HandleErrorToken(CToken* aToken) {
|
||||
NS_PRECONDITION(0!=aToken,"null token");
|
||||
nsresult result=NS_OK;
|
||||
|
||||
nsresult result=NS_OK;
|
||||
// Cycle through the remaining tokens in the token stream and handle them
|
||||
// These tokens were added so that content objects for the error message
|
||||
// are generated by the content sink
|
||||
while (PR_TRUE) {
|
||||
CToken* token = mTokenizer->PopToken();
|
||||
if(token) {
|
||||
eHTMLTokenTypes type = (eHTMLTokenTypes) token->GetTokenType();
|
||||
switch(type) {
|
||||
case eToken_newline:
|
||||
mLineNumber++; //now fall through
|
||||
case eToken_whitespace:
|
||||
case eToken_text:
|
||||
HandleLeafToken(token);
|
||||
break;
|
||||
case eToken_start:
|
||||
HandleStartToken(token);
|
||||
break;
|
||||
case eToken_end:
|
||||
HandleEndToken(token);
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// 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();
|
||||
result=(mSink)? mSink->NotifyError(error):NS_OK;
|
||||
|
||||
// Output the error to the console
|
||||
if (error) {
|
||||
char* temp;
|
||||
cerr << "XML Error in file '" << (temp = mFilename.ToNewCString()) << "', ";
|
||||
cout << "XML Error in file '" << (temp = mFilename.ToNewCString()) << "', ";
|
||||
Recycle(temp);
|
||||
cerr << "Line Number: " << error->lineNumber << ", ";
|
||||
cerr << "Col Number: " << error->colNumber << ", ";
|
||||
cerr << "Description: " << (temp = error->description.ToNewCString()) << "\n";
|
||||
cout << "Line Number: " << error->lineNumber << ", ";
|
||||
cout << "Col Number: " << error->colNumber << ", ";
|
||||
cout << "Description: " << (temp = error->description.ToNewCString()) << "\n";
|
||||
Recycle(temp);
|
||||
cerr << "Source Line: " << (temp = error->sourceLine.ToNewCString()) << "\n";
|
||||
cout << "Source Line: " << (temp = error->sourceLine.ToNewCString()) << "\n";
|
||||
Recycle(temp);
|
||||
}
|
||||
result=(mSink)? mSink->NotifyError(errTok->GetError()):NS_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче