Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
a65a56ec
Commit
a65a56ec
authored
Mar 23, 2010
by
Kyle Consalus
Committed by
Russ Cox
Mar 23, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
xml: add line numbers to syntax errors.
R=rsc CC=golang-dev
https://golang.org/cl/699041
parent
e781303e
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
49 additions
and
25 deletions
+49
-25
xml.go
src/pkg/xml/xml.go
+32
-23
xml_test.go
src/pkg/xml/xml_test.go
+17
-2
No files found.
src/pkg/xml/xml.go
View file @
a65a56ec
...
...
@@ -12,7 +12,6 @@ package xml
// TODO(rsc):
// Test error handling.
// Expose parser line number in errors.
import
(
"bufio"
...
...
@@ -26,9 +25,14 @@ import (
)
// A SyntaxError represents a syntax error in the XML input stream.
type
SyntaxError
string
type
SyntaxError
struct
{
Msg
string
Line
int
}
func
(
e
SyntaxError
)
String
()
string
{
return
"XML syntax error: "
+
string
(
e
)
}
func
(
e
*
SyntaxError
)
String
()
string
{
return
"XML syntax error on line "
+
strconv
.
Itoa
(
e
.
Line
)
+
": "
+
e
.
Msg
}
// A Name represents an XML name (Local) annotated
// with a name space identifier (Space).
...
...
@@ -344,6 +348,11 @@ func (p *Parser) pushNs(local string, url string, ok bool) {
s
.
ok
=
ok
}
// Creates a SyntaxError with the current line number.
func
(
p
*
Parser
)
syntaxError
(
msg
string
)
os
.
Error
{
return
&
SyntaxError
{
Msg
:
msg
,
Line
:
p
.
line
}
}
// Record that we are ending an element with the given name.
// The name must match the record at the top of the stack,
// which must be a pushElement record.
...
...
@@ -355,7 +364,7 @@ func (p *Parser) popElement(t *EndElement) bool {
name
:=
t
.
Name
switch
{
case
s
==
nil
||
s
.
kind
!=
stkStart
:
p
.
err
=
S
yntaxError
(
"unexpected end element </"
+
name
.
Local
+
">"
)
p
.
err
=
p
.
s
yntaxError
(
"unexpected end element </"
+
name
.
Local
+
">"
)
return
false
case
s
.
name
.
Local
!=
name
.
Local
:
if
!
p
.
Strict
{
...
...
@@ -364,10 +373,10 @@ func (p *Parser) popElement(t *EndElement) bool {
t
.
Name
=
s
.
name
return
true
}
p
.
err
=
S
yntaxError
(
"element <"
+
s
.
name
.
Local
+
"> closed by </"
+
name
.
Local
+
">"
)
p
.
err
=
p
.
s
yntaxError
(
"element <"
+
s
.
name
.
Local
+
"> closed by </"
+
name
.
Local
+
">"
)
return
false
case
s
.
name
.
Space
!=
name
.
Space
:
p
.
err
=
S
yntaxError
(
"element <"
+
s
.
name
.
Local
+
"> in space "
+
s
.
name
.
Space
+
p
.
err
=
p
.
s
yntaxError
(
"element <"
+
s
.
name
.
Local
+
"> in space "
+
s
.
name
.
Space
+
"closed by </"
+
name
.
Local
+
"> in space "
+
name
.
Space
)
return
false
}
...
...
@@ -442,7 +451,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
var
name
Name
if
name
,
ok
=
p
.
nsname
();
!
ok
{
if
p
.
err
==
nil
{
p
.
err
=
S
yntaxError
(
"expected element name after </"
)
p
.
err
=
p
.
s
yntaxError
(
"expected element name after </"
)
}
return
nil
,
p
.
err
}
...
...
@@ -451,7 +460,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
return
nil
,
p
.
err
}
if
b
!=
'>'
{
p
.
err
=
S
yntaxError
(
"invalid characters between </"
+
name
.
Local
+
" and >"
)
p
.
err
=
p
.
s
yntaxError
(
"invalid characters between </"
+
name
.
Local
+
" and >"
)
return
nil
,
p
.
err
}
return
EndElement
{
name
},
nil
...
...
@@ -463,7 +472,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
var
target
string
if
target
,
ok
=
p
.
name
();
!
ok
{
if
p
.
err
==
nil
{
p
.
err
=
S
yntaxError
(
"expected target name after <?"
)
p
.
err
=
p
.
s
yntaxError
(
"expected target name after <?"
)
}
return
nil
,
p
.
err
}
...
...
@@ -496,7 +505,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
return
nil
,
p
.
err
}
if
b
!=
'-'
{
p
.
err
=
S
yntaxError
(
"invalid sequence <!- not part of <!--"
)
p
.
err
=
p
.
s
yntaxError
(
"invalid sequence <!- not part of <!--"
)
return
nil
,
p
.
err
}
// Look for terminator.
...
...
@@ -523,7 +532,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
return
nil
,
p
.
err
}
if
b
!=
"CDATA["
[
i
]
{
p
.
err
=
S
yntaxError
(
"invalid <![ sequence"
)
p
.
err
=
p
.
s
yntaxError
(
"invalid <![ sequence"
)
return
nil
,
p
.
err
}
}
...
...
@@ -561,7 +570,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
)
if
name
,
ok
=
p
.
nsname
();
!
ok
{
if
p
.
err
==
nil
{
p
.
err
=
S
yntaxError
(
"expected element name after <"
)
p
.
err
=
p
.
s
yntaxError
(
"expected element name after <"
)
}
return
nil
,
p
.
err
}
...
...
@@ -578,7 +587,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
return
nil
,
p
.
err
}
if
b
!=
'>'
{
p
.
err
=
S
yntaxError
(
"expected /> in element"
)
p
.
err
=
p
.
s
yntaxError
(
"expected /> in element"
)
return
nil
,
p
.
err
}
break
...
...
@@ -600,7 +609,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
a
:=
&
attr
[
n
]
if
a
.
Name
,
ok
=
p
.
nsname
();
!
ok
{
if
p
.
err
==
nil
{
p
.
err
=
S
yntaxError
(
"expected attribute name in element"
)
p
.
err
=
p
.
s
yntaxError
(
"expected attribute name in element"
)
}
return
nil
,
p
.
err
}
...
...
@@ -609,7 +618,7 @@ func (p *Parser) RawToken() (Token, os.Error) {
return
nil
,
p
.
err
}
if
b
!=
'='
{
p
.
err
=
S
yntaxError
(
"attribute name without = in element"
)
p
.
err
=
p
.
s
yntaxError
(
"attribute name without = in element"
)
return
nil
,
p
.
err
}
p
.
space
()
...
...
@@ -638,7 +647,7 @@ func (p *Parser) attrval() []byte {
}
// Handle unquoted attribute values for strict parsers
if
p
.
Strict
{
p
.
err
=
S
yntaxError
(
"unquoted or missing attribute value in element"
)
p
.
err
=
p
.
s
yntaxError
(
"unquoted or missing attribute value in element"
)
return
nil
}
// Handle unquoted attribute values for unstrict parsers
...
...
@@ -707,7 +716,7 @@ func (p *Parser) getc() (b byte, ok bool) {
func
(
p
*
Parser
)
mustgetc
()
(
b
byte
,
ok
bool
)
{
if
b
,
ok
=
p
.
getc
();
!
ok
{
if
p
.
err
==
os
.
EOF
{
p
.
err
=
S
yntaxError
(
"unexpected EOF"
)
p
.
err
=
p
.
s
yntaxError
(
"unexpected EOF"
)
}
}
return
...
...
@@ -751,14 +760,14 @@ Input:
trunc
=
2
break
Input
}
p
.
err
=
S
yntaxError
(
"unescaped ]]> not in CDATA section"
)
p
.
err
=
p
.
s
yntaxError
(
"unescaped ]]> not in CDATA section"
)
return
nil
}
// Stop reading text if we see a <.
if
b
==
'<'
&&
!
cdata
{
if
quote
>=
0
{
p
.
err
=
S
yntaxError
(
"unescaped < inside quoted string"
)
p
.
err
=
p
.
s
yntaxError
(
"unescaped < inside quoted string"
)
return
nil
}
p
.
ungetc
(
'<'
)
...
...
@@ -779,7 +788,7 @@ Input:
p
.
tmp
[
i
],
p
.
err
=
p
.
r
.
ReadByte
()
if
p
.
err
!=
nil
{
if
p
.
err
==
os
.
EOF
{
p
.
err
=
S
yntaxError
(
"unexpected EOF"
)
p
.
err
=
p
.
s
yntaxError
(
"unexpected EOF"
)
}
return
nil
}
...
...
@@ -804,7 +813,7 @@ Input:
p
.
buf
.
Write
(
p
.
tmp
[
0
:
i
])
continue
Input
}
p
.
err
=
S
yntaxError
(
"character entity expression &"
+
s
+
"... too long"
)
p
.
err
=
p
.
s
yntaxError
(
"character entity expression &"
+
s
+
"... too long"
)
return
nil
}
var
haveText
bool
...
...
@@ -836,7 +845,7 @@ Input:
p
.
buf
.
Write
(
p
.
tmp
[
0
:
i
])
continue
Input
}
p
.
err
=
S
yntaxError
(
"invalid character entity &"
+
s
+
";"
)
p
.
err
=
p
.
s
yntaxError
(
"invalid character entity &"
+
s
+
";"
)
return
nil
}
p
.
buf
.
Write
([]
byte
(
text
))
...
...
@@ -913,7 +922,7 @@ func (p *Parser) name() (s string, ok bool) {
s
=
p
.
buf
.
String
()
for
i
,
c
:=
range
s
{
if
!
unicode
.
Is
(
first
,
c
)
&&
(
i
==
0
||
!
unicode
.
Is
(
second
,
c
))
{
p
.
err
=
S
yntaxError
(
"invalid XML name: "
+
s
)
p
.
err
=
p
.
s
yntaxError
(
"invalid XML name: "
+
s
)
return
""
,
false
}
}
...
...
src/pkg/xml/xml_test.go
View file @
a65a56ec
...
...
@@ -209,7 +209,7 @@ func TestSyntax(t *testing.T) {
var
err
os
.
Error
for
_
,
err
=
p
.
Token
();
err
==
nil
;
_
,
err
=
p
.
Token
()
{
}
if
_
,
ok
:=
err
.
(
SyntaxError
);
!
ok
{
if
_
,
ok
:=
err
.
(
*
SyntaxError
);
!
ok
{
t
.
Fatalf
(
`xmlInput "%s": expected SyntaxError not received`
,
xmlInput
[
i
])
}
}
...
...
@@ -314,7 +314,7 @@ func TestUnquotedAttrs(t *testing.T) {
p
:=
NewParser
(
StringReader
(
data
))
p
.
Strict
=
false
token
,
err
:=
p
.
Token
()
if
_
,
ok
:=
err
.
(
SyntaxError
);
ok
{
if
_
,
ok
:=
err
.
(
*
SyntaxError
);
ok
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
if
token
.
(
StartElement
)
.
Name
.
Local
!=
"tag"
{
...
...
@@ -354,3 +354,18 @@ func TestCopyTokenStartElement(t *testing.T) {
t
.
Error
(
"CopyToken(CharData) uses same buffer."
)
}
}
func
TestSyntaxErrorLineNum
(
t
*
testing
.
T
)
{
testInput
:=
"<P>Foo<P>
\n\n
<P>Bar</>
\n
"
p
:=
NewParser
(
StringReader
(
testInput
))
var
err
os
.
Error
for
_
,
err
=
p
.
Token
();
err
==
nil
;
_
,
err
=
p
.
Token
()
{
}
synerr
,
ok
:=
err
.
(
*
SyntaxError
)
if
!
ok
{
t
.
Error
(
"Expected SyntaxError."
)
}
if
synerr
.
Line
!=
3
{
t
.
Error
(
"SyntaxError didn't have correct line number."
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment