mirror of
https://github.com/golang/go
synced 2024-11-22 06:24:38 -07:00
XML lexing
The lexer is the bottom level. Most clients will use the Unmarshal method, not yet implemented, which will behave like json.Unmarshal. R=r DELTA=1115 (766 added, 219 deleted, 130 changed) OCL=35316 CL=35339
This commit is contained in:
parent
2b1dbe8a4f
commit
a91b6b74e3
1056
src/pkg/xml/xml.go
1056
src/pkg/xml/xml.go
File diff suppressed because it is too large
Load Diff
149
src/pkg/xml/xml_test.go
Normal file
149
src/pkg/xml/xml_test.go
Normal file
@ -0,0 +1,149 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package xml
|
||||
|
||||
import (
|
||||
"io";
|
||||
"os";
|
||||
"reflect";
|
||||
"strings";
|
||||
"testing";
|
||||
)
|
||||
|
||||
const testInput = `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<body xmlns:foo="ns1" xmlns="ns2" xmlns:tag="ns3" ` "\r\n\t" ` >
|
||||
<hello lang="en">World <>'" 白鵬翔</hello>
|
||||
<goodbye />
|
||||
<outer foo:attr="value" xmlns:tag="ns4">
|
||||
<inner/>
|
||||
</outer>
|
||||
<tag:name>
|
||||
Some text here.
|
||||
</tag:name>
|
||||
</body><!-- missing final newline -->`
|
||||
|
||||
var rawTokens = []Token{
|
||||
CharData(strings.Bytes("\n")),
|
||||
ProcInst{"xml", strings.Bytes(`version="1.0" encoding="UTF-8"`)},
|
||||
CharData(strings.Bytes("\n")),
|
||||
Directive(strings.Bytes(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`)),
|
||||
CharData(strings.Bytes("\n")),
|
||||
StartElement{Name{"", "body"}, []Attr{Attr{Name{"xmlns", "foo"}, "ns1"}, Attr{Name{"", "xmlns"}, "ns2"}, Attr{Name{"xmlns", "tag"}, "ns3"}}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"", "hello"}, []Attr{Attr{Name{"", "lang"}, "en"}}},
|
||||
CharData(strings.Bytes("World <>'\" 白鵬翔")),
|
||||
EndElement{Name{"", "hello"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"", "goodbye"}, nil},
|
||||
EndElement{Name{"", "goodbye"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"", "outer"}, []Attr{Attr{Name{"foo", "attr"}, "value"}, Attr{Name{"xmlns", "tag"}, "ns4"}}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"", "inner"}, nil},
|
||||
EndElement{Name{"", "inner"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
EndElement{Name{"", "outer"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"tag", "name"}, nil},
|
||||
CharData(strings.Bytes("\n Some text here.\n ")),
|
||||
EndElement{Name{"tag", "name"}},
|
||||
CharData(strings.Bytes("\n")),
|
||||
EndElement{Name{"", "body"}},
|
||||
Comment(strings.Bytes(" missing final newline ")),
|
||||
}
|
||||
|
||||
var cookedTokens = []Token{
|
||||
CharData(strings.Bytes("\n")),
|
||||
ProcInst{"xml", strings.Bytes(`version="1.0" encoding="UTF-8"`)},
|
||||
CharData(strings.Bytes("\n")),
|
||||
Directive(strings.Bytes(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`)),
|
||||
CharData(strings.Bytes("\n")),
|
||||
StartElement{Name{"ns2", "body"}, []Attr{Attr{Name{"xmlns", "foo"}, "ns1"}, Attr{Name{"", "xmlns"}, "ns2"}, Attr{Name{"xmlns", "tag"}, "ns3"}}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"ns2", "hello"}, []Attr{Attr{Name{"", "lang"}, "en"}}},
|
||||
CharData(strings.Bytes("World <>'\" 白鵬翔")),
|
||||
EndElement{Name{"ns2", "hello"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"ns2", "goodbye"}, nil},
|
||||
EndElement{Name{"ns2", "goodbye"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"ns2", "outer"}, []Attr{Attr{Name{"ns1", "attr"}, "value"}, Attr{Name{"xmlns", "tag"}, "ns4"}}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"ns2", "inner"}, nil},
|
||||
EndElement{Name{"ns2", "inner"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
EndElement{Name{"ns2", "outer"}},
|
||||
CharData(strings.Bytes("\n ")),
|
||||
StartElement{Name{"ns3", "name"}, nil},
|
||||
CharData(strings.Bytes("\n Some text here.\n ")),
|
||||
EndElement{Name{"ns3", "name"}},
|
||||
CharData(strings.Bytes("\n")),
|
||||
EndElement{Name{"ns2", "body"}},
|
||||
Comment(strings.Bytes(" missing final newline ")),
|
||||
}
|
||||
|
||||
type stringReader struct {
|
||||
s string;
|
||||
off int;
|
||||
}
|
||||
|
||||
func (r *stringReader) Read(b []byte) (n int, err os.Error) {
|
||||
if r.off >= len(r.s) {
|
||||
return 0, os.EOF;
|
||||
}
|
||||
for r.off < len(r.s) && n < len(b) {
|
||||
b[n] = r.s[r.off];
|
||||
n++;
|
||||
r.off++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
func (r *stringReader) ReadByte() (b byte, err os.Error) {
|
||||
if r.off >= len(r.s) {
|
||||
return 0, os.EOF;
|
||||
}
|
||||
b = r.s[r.off];
|
||||
r.off++;
|
||||
return;
|
||||
}
|
||||
|
||||
func StringReader(s string) io.Reader {
|
||||
return &stringReader{s, 0}
|
||||
}
|
||||
|
||||
func TestRawToken(t *testing.T) {
|
||||
p := NewParser(StringReader(testInput));
|
||||
|
||||
for i, want := range rawTokens {
|
||||
have, err := p.RawToken();
|
||||
if err != nil {
|
||||
t.Fatalf("token %d: unexpected error: %s", i, err);
|
||||
}
|
||||
if !reflect.DeepEqual(have, want) {
|
||||
t.Errorf("token %d = %#v want %#v", i, have, want);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestToken(t *testing.T) {
|
||||
p := NewParser(StringReader(testInput));
|
||||
|
||||
for i, want := range cookedTokens {
|
||||
have, err := p.Token();
|
||||
if err != nil {
|
||||
t.Fatalf("token %d: unexpected error: %s", i, err);
|
||||
}
|
||||
if !reflect.DeepEqual(have, want) {
|
||||
t.Errorf("token %d = %#v want %#v", i, have, want);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user