aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/xml
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
commitadb0401dac41c81571722312d4586b2693f95aa6 (patch)
treeea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/xml
parent5548ca3540bccbc908a45942896d635ea5f1c23f (diff)
downloadgcc-adb0401dac41c81571722312d4586b2693f95aa6.zip
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.gz
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.bz2
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/xml')
-rw-r--r--libgo/go/xml/atom_test.go50
-rw-r--r--libgo/go/xml/embed_test.go10
-rw-r--r--libgo/go/xml/marshal.go228
-rw-r--r--libgo/go/xml/marshal_test.go305
-rw-r--r--libgo/go/xml/read.go128
-rw-r--r--libgo/go/xml/read_test.go78
-rw-r--r--libgo/go/xml/xml.go636
-rw-r--r--libgo/go/xml/xml_test.go29
8 files changed, 1069 insertions, 395 deletions
diff --git a/libgo/go/xml/atom_test.go b/libgo/go/xml/atom_test.go
new file mode 100644
index 0000000..d365510
--- /dev/null
+++ b/libgo/go/xml/atom_test.go
@@ -0,0 +1,50 @@
+// Copyright 2011 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
+
+var atomValue = &Feed{
+ Title: "Example Feed",
+ Link: []Link{{Href: "http://example.org/"}},
+ Updated: ParseTime("2003-12-13T18:30:02Z"),
+ Author: Person{Name: "John Doe"},
+ Id: "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6",
+
+ Entry: []Entry{
+ {
+ Title: "Atom-Powered Robots Run Amok",
+ Link: []Link{{Href: "http://example.org/2003/12/13/atom03"}},
+ Id: "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
+ Updated: ParseTime("2003-12-13T18:30:02Z"),
+ Summary: NewText("Some text."),
+ },
+ },
+}
+
+var atomXml = `` +
+ `<feed xmlns="http://www.w3.org/2005/Atom">` +
+ `<Title>Example Feed</Title>` +
+ `<Id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</Id>` +
+ `<Link href="http://example.org/"></Link>` +
+ `<Updated>2003-12-13T18:30:02Z</Updated>` +
+ `<Author><Name>John Doe</Name><URI></URI><Email></Email></Author>` +
+ `<Entry>` +
+ `<Title>Atom-Powered Robots Run Amok</Title>` +
+ `<Id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</Id>` +
+ `<Link href="http://example.org/2003/12/13/atom03"></Link>` +
+ `<Updated>2003-12-13T18:30:02Z</Updated>` +
+ `<Author><Name></Name><URI></URI><Email></Email></Author>` +
+ `<Summary>Some text.</Summary>` +
+ `</Entry>` +
+ `</feed>`
+
+func ParseTime(str string) Time {
+ return Time(str)
+}
+
+func NewText(text string) Text {
+ return Text{
+ Body: text,
+ }
+}
diff --git a/libgo/go/xml/embed_test.go b/libgo/go/xml/embed_test.go
index abfe781..ec7f478 100644
--- a/libgo/go/xml/embed_test.go
+++ b/libgo/go/xml/embed_test.go
@@ -12,14 +12,14 @@ type C struct {
}
type A struct {
- XMLName Name "http://domain a"
+ XMLName Name `xml:"http://domain a"`
C
B B
FieldA string
}
type B struct {
- XMLName Name "b"
+ XMLName Name `xml:"b"`
C
FieldB string
}
@@ -65,7 +65,7 @@ func TestEmbedded1(t *testing.T) {
}
type A2 struct {
- XMLName Name "http://domain a"
+ XMLName Name `xml:"http://domain a"`
XY string
Xy string
}
@@ -92,7 +92,7 @@ func TestEmbedded2(t *testing.T) {
}
type A3 struct {
- XMLName Name "http://domain a"
+ XMLName Name `xml:"http://domain a"`
xy string
}
@@ -108,7 +108,7 @@ func TestEmbedded3(t *testing.T) {
}
type A4 struct {
- XMLName Name "http://domain a"
+ XMLName Name `xml:"http://domain a"`
Any string
}
diff --git a/libgo/go/xml/marshal.go b/libgo/go/xml/marshal.go
new file mode 100644
index 0000000..ea421c1
--- /dev/null
+++ b/libgo/go/xml/marshal.go
@@ -0,0 +1,228 @@
+// Copyright 2011 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 (
+ "bufio"
+ "io"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+const (
+ // A generic XML header suitable for use with the output of Marshal and
+ // MarshalIndent. This is not automatically added to any output of this
+ // package, it is provided as a convenience.
+ Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
+)
+
+// A Marshaler can produce well-formatted XML representing its internal state.
+// It is used by both Marshal and MarshalIndent.
+type Marshaler interface {
+ MarshalXML() ([]byte, os.Error)
+}
+
+type printer struct {
+ *bufio.Writer
+}
+
+// Marshal writes an XML-formatted representation of v to w.
+//
+// If v implements Marshaler, then Marshal calls its MarshalXML method.
+// Otherwise, Marshal uses the following procedure to create the XML.
+//
+// Marshal handles an array or slice by marshalling each of the elements.
+// Marshal handles a pointer by marshalling the value it points at or, if the
+// pointer is nil, by writing nothing. Marshal handles an interface value by
+// marshalling the value it contains or, if the interface value is nil, by
+// writing nothing. Marshal handles all other data by writing a single XML
+// element containing the data.
+//
+// The name of that XML element is taken from, in order of preference:
+// - the tag on an XMLName field, if the data is a struct
+// - the value of an XMLName field of type xml.Name
+// - the tag of the struct field used to obtain the data
+// - the name of the struct field used to obtain the data
+// - the name '???'.
+//
+// The XML element for a struct contains marshalled elements for each of the
+// exported fields of the struct, with these exceptions:
+// - the XMLName field, described above, is omitted.
+// - a field with tag "attr" becomes an attribute in the XML element.
+// - a field with tag "chardata" is written as character data,
+// not as an XML element.
+// - a field with tag "innerxml" is written verbatim,
+// not subject to the usual marshalling procedure.
+//
+// Marshal will return an error if asked to marshal a channel, function, or map.
+func Marshal(w io.Writer, v interface{}) (err os.Error) {
+ p := &printer{bufio.NewWriter(w)}
+ err = p.marshalValue(reflect.ValueOf(v), "???")
+ p.Flush()
+ return err
+}
+
+func (p *printer) marshalValue(val reflect.Value, name string) os.Error {
+ if !val.IsValid() {
+ return nil
+ }
+
+ kind := val.Kind()
+ typ := val.Type()
+
+ // Try Marshaler
+ if typ.NumMethod() > 0 {
+ if marshaler, ok := val.Interface().(Marshaler); ok {
+ bytes, err := marshaler.MarshalXML()
+ if err != nil {
+ return err
+ }
+ p.Write(bytes)
+ return nil
+ }
+ }
+
+ // Drill into pointers/interfaces
+ if kind == reflect.Ptr || kind == reflect.Interface {
+ if val.IsNil() {
+ return nil
+ }
+ return p.marshalValue(val.Elem(), name)
+ }
+
+ // Slices and arrays iterate over the elements. They do not have an enclosing tag.
+ if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
+ for i, n := 0, val.Len(); i < n; i++ {
+ if err := p.marshalValue(val.Index(i), name); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ // Find XML name
+ xmlns := ""
+ if kind == reflect.Struct {
+ if f, ok := typ.FieldByName("XMLName"); ok {
+ if tag := f.Tag.Get("xml"); tag != "" {
+ if i := strings.Index(tag, " "); i >= 0 {
+ xmlns, name = tag[:i], tag[i+1:]
+ } else {
+ name = tag
+ }
+ } else if v, ok := val.FieldByIndex(f.Index).Interface().(Name); ok && v.Local != "" {
+ xmlns, name = v.Space, v.Local
+ }
+ }
+ }
+
+ p.WriteByte('<')
+ p.WriteString(name)
+
+ // Attributes
+ if kind == reflect.Struct {
+ if len(xmlns) > 0 {
+ p.WriteString(` xmlns="`)
+ Escape(p, []byte(xmlns))
+ p.WriteByte('"')
+ }
+
+ for i, n := 0, typ.NumField(); i < n; i++ {
+ if f := typ.Field(i); f.PkgPath == "" && f.Tag.Get("xml") == "attr" {
+ if f.Type.Kind() == reflect.String {
+ if str := val.Field(i).String(); str != "" {
+ p.WriteByte(' ')
+ p.WriteString(strings.ToLower(f.Name))
+ p.WriteString(`="`)
+ Escape(p, []byte(str))
+ p.WriteByte('"')
+ }
+ }
+ }
+ }
+ }
+ p.WriteByte('>')
+
+ switch k := val.Kind(); k {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ p.WriteString(strconv.Itoa64(val.Int()))
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ p.WriteString(strconv.Uitoa64(val.Uint()))
+ case reflect.Float32, reflect.Float64:
+ p.WriteString(strconv.Ftoa64(val.Float(), 'g', -1))
+ case reflect.String:
+ Escape(p, []byte(val.String()))
+ case reflect.Bool:
+ p.WriteString(strconv.Btoa(val.Bool()))
+ case reflect.Array:
+ // will be [...]byte
+ bytes := make([]byte, val.Len())
+ for i := range bytes {
+ bytes[i] = val.Index(i).Interface().(byte)
+ }
+ Escape(p, bytes)
+ case reflect.Slice:
+ // will be []byte
+ bytes := val.Interface().([]byte)
+ Escape(p, bytes)
+ case reflect.Struct:
+ for i, n := 0, val.NumField(); i < n; i++ {
+ if f := typ.Field(i); f.Name != "XMLName" && f.PkgPath == "" {
+ name := f.Name
+ switch tag := f.Tag.Get("xml"); tag {
+ case "":
+ case "chardata":
+ if tk := f.Type.Kind(); tk == reflect.String {
+ Escape(p, []byte(val.Field(i).String()))
+ } else if tk == reflect.Slice {
+ if elem, ok := val.Field(i).Interface().([]byte); ok {
+ Escape(p, elem)
+ }
+ }
+ continue
+ case "innerxml":
+ iface := val.Field(i).Interface()
+ switch raw := iface.(type) {
+ case []byte:
+ p.Write(raw)
+ continue
+ case string:
+ p.WriteString(raw)
+ continue
+ }
+ case "attr":
+ continue
+ default:
+ name = tag
+ }
+
+ if err := p.marshalValue(val.Field(i), name); err != nil {
+ return err
+ }
+ }
+ }
+ default:
+ return &UnsupportedTypeError{typ}
+ }
+
+ p.WriteByte('<')
+ p.WriteByte('/')
+ p.WriteString(name)
+ p.WriteByte('>')
+
+ return nil
+}
+
+// A MarshalXMLError is returned when Marshal or MarshalIndent encounter a type
+// that cannot be converted into XML.
+type UnsupportedTypeError struct {
+ Type reflect.Type
+}
+
+func (e *UnsupportedTypeError) String() string {
+ return "xml: unsupported type: " + e.Type.String()
+}
diff --git a/libgo/go/xml/marshal_test.go b/libgo/go/xml/marshal_test.go
new file mode 100644
index 0000000..5b972fa
--- /dev/null
+++ b/libgo/go/xml/marshal_test.go
@@ -0,0 +1,305 @@
+// Copyright 2011 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 (
+ "reflect"
+ "testing"
+
+ "os"
+ "bytes"
+ "strings"
+ "strconv"
+)
+
+type DriveType int
+
+const (
+ HyperDrive DriveType = iota
+ ImprobabilityDrive
+)
+
+type Passenger struct {
+ Name []string `xml:"name"`
+ Weight float32 `xml:"weight"`
+}
+
+type Ship struct {
+ XMLName Name `xml:"spaceship"`
+
+ Name string `xml:"attr"`
+ Pilot string `xml:"attr"`
+ Drive DriveType `xml:"drive"`
+ Age uint `xml:"age"`
+ Passenger []*Passenger `xml:"passenger"`
+ secret string
+}
+
+type RawXML string
+
+func (rx RawXML) MarshalXML() ([]byte, os.Error) {
+ return []byte(rx), nil
+}
+
+type NamedType string
+
+type Port struct {
+ XMLName Name `xml:"port"`
+ Type string `xml:"attr"`
+ Number string `xml:"chardata"`
+}
+
+type Domain struct {
+ XMLName Name `xml:"domain"`
+ Country string `xml:"attr"`
+ Name []byte `xml:"chardata"`
+}
+
+type Book struct {
+ XMLName Name `xml:"book"`
+ Title string `xml:"chardata"`
+}
+
+type SecretAgent struct {
+ XMLName Name `xml:"agent"`
+ Handle string `xml:"attr"`
+ Identity string
+ Obfuscate string `xml:"innerxml"`
+}
+
+var nilStruct *Ship
+
+var marshalTests = []struct {
+ Value interface{}
+ ExpectXML string
+}{
+ // Test nil marshals to nothing
+ {Value: nil, ExpectXML: ``},
+ {Value: nilStruct, ExpectXML: ``},
+
+ // Test value types (no tag name, so ???)
+ {Value: true, ExpectXML: `<???>true</???>`},
+ {Value: int(42), ExpectXML: `<???>42</???>`},
+ {Value: int8(42), ExpectXML: `<???>42</???>`},
+ {Value: int16(42), ExpectXML: `<???>42</???>`},
+ {Value: int32(42), ExpectXML: `<???>42</???>`},
+ {Value: uint(42), ExpectXML: `<???>42</???>`},
+ {Value: uint8(42), ExpectXML: `<???>42</???>`},
+ {Value: uint16(42), ExpectXML: `<???>42</???>`},
+ {Value: uint32(42), ExpectXML: `<???>42</???>`},
+ {Value: float32(1.25), ExpectXML: `<???>1.25</???>`},
+ {Value: float64(1.25), ExpectXML: `<???>1.25</???>`},
+ {Value: uintptr(0xFFDD), ExpectXML: `<???>65501</???>`},
+ {Value: "gopher", ExpectXML: `<???>gopher</???>`},
+ {Value: []byte("gopher"), ExpectXML: `<???>gopher</???>`},
+ {Value: "</>", ExpectXML: `<???>&lt;/&gt;</???>`},
+ {Value: []byte("</>"), ExpectXML: `<???>&lt;/&gt;</???>`},
+ {Value: [3]byte{'<', '/', '>'}, ExpectXML: `<???>&lt;/&gt;</???>`},
+ {Value: NamedType("potato"), ExpectXML: `<???>potato</???>`},
+ {Value: []int{1, 2, 3}, ExpectXML: `<???>1</???><???>2</???><???>3</???>`},
+ {Value: [3]int{1, 2, 3}, ExpectXML: `<???>1</???><???>2</???><???>3</???>`},
+
+ // Test innerxml
+ {Value: RawXML("</>"), ExpectXML: `</>`},
+ {
+ Value: &SecretAgent{
+ Handle: "007",
+ Identity: "James Bond",
+ Obfuscate: "<redacted/>",
+ },
+ //ExpectXML: `<agent handle="007"><redacted/></agent>`,
+ ExpectXML: `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+ },
+
+ // Test structs
+ {Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
+ {Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
+ {Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="&lt;unix&gt;"></port>`},
+ {Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&amp;friends</domain>`},
+ {Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride &amp; Prejudice</book>`},
+ {Value: atomValue, ExpectXML: atomXml},
+ {
+ Value: &Ship{
+ Name: "Heart of Gold",
+ Pilot: "Computer",
+ Age: 1,
+ Drive: ImprobabilityDrive,
+ Passenger: []*Passenger{
+ &Passenger{
+ Name: []string{"Zaphod", "Beeblebrox"},
+ Weight: 7.25,
+ },
+ &Passenger{
+ Name: []string{"Trisha", "McMillen"},
+ Weight: 5.5,
+ },
+ &Passenger{
+ Name: []string{"Ford", "Prefect"},
+ Weight: 7,
+ },
+ &Passenger{
+ Name: []string{"Arthur", "Dent"},
+ Weight: 6.75,
+ },
+ },
+ },
+ ExpectXML: `<spaceship name="Heart of Gold" pilot="Computer">` +
+ `<drive>` + strconv.Itoa(int(ImprobabilityDrive)) + `</drive>` +
+ `<age>1</age>` +
+ `<passenger>` +
+ `<name>Zaphod</name>` +
+ `<name>Beeblebrox</name>` +
+ `<weight>7.25</weight>` +
+ `</passenger>` +
+ `<passenger>` +
+ `<name>Trisha</name>` +
+ `<name>McMillen</name>` +
+ `<weight>5.5</weight>` +
+ `</passenger>` +
+ `<passenger>` +
+ `<name>Ford</name>` +
+ `<name>Prefect</name>` +
+ `<weight>7</weight>` +
+ `</passenger>` +
+ `<passenger>` +
+ `<name>Arthur</name>` +
+ `<name>Dent</name>` +
+ `<weight>6.75</weight>` +
+ `</passenger>` +
+ `</spaceship>`,
+ },
+}
+
+func TestMarshal(t *testing.T) {
+ for idx, test := range marshalTests {
+ buf := bytes.NewBuffer(nil)
+ err := Marshal(buf, test.Value)
+ if err != nil {
+ t.Errorf("#%d: Error: %s", idx, err)
+ continue
+ }
+ if got, want := buf.String(), test.ExpectXML; got != want {
+ if strings.Contains(want, "\n") {
+ t.Errorf("#%d: marshal(%#v) - GOT:\n%s\nWANT:\n%s", idx, test.Value, got, want)
+ } else {
+ t.Errorf("#%d: marshal(%#v) = %#q want %#q", idx, test.Value, got, want)
+ }
+ }
+ }
+}
+
+var marshalErrorTests = []struct {
+ Value interface{}
+ ExpectErr string
+ ExpectKind reflect.Kind
+}{
+ {
+ Value: make(chan bool),
+ ExpectErr: "xml: unsupported type: chan bool",
+ ExpectKind: reflect.Chan,
+ },
+ {
+ Value: map[string]string{
+ "question": "What do you get when you multiply six by nine?",
+ "answer": "42",
+ },
+ ExpectErr: "xml: unsupported type: map[string] string",
+ ExpectKind: reflect.Map,
+ },
+ {
+ Value: map[*Ship]bool{nil: false},
+ ExpectErr: "xml: unsupported type: map[*xml.Ship] bool",
+ ExpectKind: reflect.Map,
+ },
+}
+
+func TestMarshalErrors(t *testing.T) {
+ for idx, test := range marshalErrorTests {
+ buf := bytes.NewBuffer(nil)
+ err := Marshal(buf, test.Value)
+ if got, want := err, test.ExpectErr; got == nil {
+ t.Errorf("#%d: want error %s", idx, want)
+ continue
+ } else if got.String() != want {
+ t.Errorf("#%d: marshal(%#v) = [error] %q, want %q", idx, test.Value, got, want)
+ }
+ if got, want := err.(*UnsupportedTypeError).Type.Kind(), test.ExpectKind; got != want {
+ t.Errorf("#%d: marshal(%#v) = [error kind] %s, want %s", idx, test.Value, got, want)
+ }
+ }
+}
+
+// Do invertibility testing on the various structures that we test
+func TestUnmarshal(t *testing.T) {
+ for i, test := range marshalTests {
+ // Skip the nil pointers
+ if i <= 1 {
+ continue
+ }
+
+ var dest interface{}
+
+ switch test.Value.(type) {
+ case *Ship, Ship:
+ dest = &Ship{}
+ case *Port, Port:
+ dest = &Port{}
+ case *Domain, Domain:
+ dest = &Domain{}
+ case *Feed, Feed:
+ dest = &Feed{}
+ default:
+ continue
+ }
+
+ buffer := bytes.NewBufferString(test.ExpectXML)
+ err := Unmarshal(buffer, dest)
+
+ // Don't compare XMLNames
+ switch fix := dest.(type) {
+ case *Ship:
+ fix.XMLName = Name{}
+ case *Port:
+ fix.XMLName = Name{}
+ case *Domain:
+ fix.XMLName = Name{}
+ case *Feed:
+ fix.XMLName = Name{}
+ fix.Author.InnerXML = ""
+ for i := range fix.Entry {
+ fix.Entry[i].Author.InnerXML = ""
+ }
+ }
+
+ if err != nil {
+ t.Errorf("#%d: unexpected error: %#v", i, err)
+ } else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
+ t.Errorf("#%d: unmarshal(%#s) = %#v, want %#v", i, test.ExpectXML, got, want)
+ }
+ }
+}
+
+func BenchmarkMarshal(b *testing.B) {
+ idx := len(marshalTests) - 1
+ test := marshalTests[idx]
+
+ buf := bytes.NewBuffer(nil)
+ for i := 0; i < b.N; i++ {
+ Marshal(buf, test.Value)
+ buf.Truncate(0)
+ }
+}
+
+func BenchmarkUnmarshal(b *testing.B) {
+ idx := len(marshalTests) - 1
+ test := marshalTests[idx]
+ sm := &Ship{}
+ xml := []byte(test.ExpectXML)
+
+ for i := 0; i < b.N; i++ {
+ buffer := bytes.NewBuffer(xml)
+ Unmarshal(buffer, sm)
+ }
+}
diff --git a/libgo/go/xml/read.go b/libgo/go/xml/read.go
index e2b349c..786b69f 100644
--- a/libgo/go/xml/read.go
+++ b/libgo/go/xml/read.go
@@ -31,16 +31,16 @@ import (
// For example, given these definitions:
//
// type Email struct {
-// Where string "attr"
+// Where string `xml:"attr"`
// Addr string
// }
//
// type Result struct {
-// XMLName xml.Name "result"
+// XMLName xml.Name `xml:"result"`
// Name string
// Phone string
// Email []Email
-// Groups []string "group>value"
+// Groups []string `xml:"group>value"`
// }
//
// result := Result{Name: "name", Phone: "phone", Email: nil}
@@ -79,11 +79,13 @@ import (
// Groups was assigned considering the element path provided in the
// field tag.
//
-// Because Unmarshal uses the reflect package, it can only
-// assign to upper case fields. Unmarshal uses a case-insensitive
+// Because Unmarshal uses the reflect package, it can only assign
+// to exported (upper case) fields. Unmarshal uses a case-insensitive
// comparison to match XML element names to struct field names.
//
-// Unmarshal maps an XML element to a struct using the following rules:
+// Unmarshal maps an XML element to a struct using the following rules.
+// In the rules, the tag of a field refers to the value associated with the
+// key 'xml' in the struct field's tag (see the example above).
//
// * If the struct has a field of type []byte or string with tag "innerxml",
// Unmarshal accumulates the raw XML nested inside the element
@@ -92,9 +94,9 @@ import (
// * If the struct has a field named XMLName of type xml.Name,
// Unmarshal records the element name in that field.
//
-// * If the XMLName field has an associated tag string of the form
-// "tag" or "namespace-URL tag", the XML element must have
-// the given tag (and, optionally, name space) or else Unmarshal
+// * If the XMLName field has an associated tag of the form
+// "name" or "namespace-URL name", the XML element must have
+// the given name (and, optionally, name space) or else Unmarshal
// returns an error.
//
// * If the XML element has an attribute whose name matches a
@@ -106,31 +108,41 @@ import (
// The struct field may have type []byte or string.
// If there is no such field, the character data is discarded.
//
+// * If the XML element contains comments, they are accumulated in
+// the first struct field that has tag "comments". The struct
+// field may have type []byte or string. If there is no such
+// field, the comments are discarded.
+//
// * If the XML element contains a sub-element whose name matches
-// the prefix of a struct field tag formatted as "a>b>c", unmarshal
+// the prefix of a tag formatted as "a>b>c", unmarshal
// will descend into the XML structure looking for elements with the
// given names, and will map the innermost elements to that struct field.
-// A struct field tag starting with ">" is equivalent to one starting
+// A tag starting with ">" is equivalent to one starting
// with the field name followed by ">".
//
// * If the XML element contains a sub-element whose name
-// matches a struct field whose tag is neither "attr" nor "chardata",
+// matches a field whose tag is neither "attr" nor "chardata",
// Unmarshal maps the sub-element to that struct field.
// Otherwise, if the struct has a field named Any, unmarshal
// maps the sub-element to that struct field.
//
// Unmarshal maps an XML element to a string or []byte by saving the
-// concatenation of that element's character data in the string or []byte.
+// concatenation of that element's character data in the string or
+// []byte.
+//
+// Unmarshal maps an attribute value to a string or []byte by saving
+// the value in the string or slice.
//
-// Unmarshal maps an XML element to a slice by extending the length
-// of the slice and mapping the element to the newly created value.
+// Unmarshal maps an XML element to a slice by extending the length of
+// the slice and mapping the element to the newly created value.
//
-// Unmarshal maps an XML element to a bool by setting it to the boolean
-// value represented by the string.
+// Unmarshal maps an XML element or attribute value to a bool by
+// setting it to the boolean value represented by the string.
//
-// Unmarshal maps an XML element to an integer or floating-point
-// field by setting the field to the result of interpreting the string
-// value in decimal. There is no check for overflow.
+// Unmarshal maps an XML element or attribute value to an integer or
+// floating-point field by setting the field to the result of
+// interpreting the string value in decimal. There is no check for
+// overflow.
//
// Unmarshal maps an XML element to an xml.Name by recording the
// element name.
@@ -241,7 +253,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
switch v := val; v.Kind() {
default:
- return os.ErrorString("unknown type " + v.Type().String())
+ return os.NewError("unknown type " + v.Type().String())
case reflect.Slice:
typ := v.Type()
@@ -287,8 +299,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
// Assign name.
if f, ok := typ.FieldByName("XMLName"); ok {
// Validate element name.
- if f.Tag != "" {
- tag := f.Tag
+ if tag := f.Tag.Get("xml"); tag != "" {
ns := ""
i := strings.LastIndex(tag, " ")
if i >= 0 {
@@ -320,12 +331,9 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
// Also, determine whether we need to save character data or comments.
for i, n := 0, typ.NumField(); i < n; i++ {
f := typ.Field(i)
- switch f.Tag {
+ switch f.Tag.Get("xml") {
case "attr":
strv := sv.FieldByIndex(f.Index)
- if strv.Kind() != reflect.String {
- return UnmarshalError(sv.Type().String() + " field " + f.Name + " has attr tag but is not type string")
- }
// Look for attribute.
val := ""
k := strings.ToLower(f.Name)
@@ -335,7 +343,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
break
}
}
- strv.SetString(val)
+ copyValue(strv, []byte(val))
case "comment":
if !saveComment.IsValid() {
@@ -359,15 +367,15 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
}
default:
- if strings.Contains(f.Tag, ">") {
+ if tag := f.Tag.Get("xml"); strings.Contains(tag, ">") {
if fieldPaths == nil {
fieldPaths = make(map[string]pathInfo)
}
- path := strings.ToLower(f.Tag)
- if strings.HasPrefix(f.Tag, ">") {
+ path := strings.ToLower(tag)
+ if strings.HasPrefix(tag, ">") {
path = strings.ToLower(f.Name) + path
}
- if strings.HasSuffix(f.Tag, ">") {
+ if strings.HasSuffix(tag, ">") {
path = path[:len(path)-1]
}
err := addFieldPath(sv, fieldPaths, path, f.Index)
@@ -454,33 +462,54 @@ Loop:
}
}
- var err os.Error
+ if err := copyValue(saveData, data); err != nil {
+ return err
+ }
+
+ switch t := saveComment; t.Kind() {
+ case reflect.String:
+ t.SetString(string(comment))
+ case reflect.Slice:
+ t.Set(reflect.ValueOf(comment))
+ }
+
+ switch t := saveXML; t.Kind() {
+ case reflect.String:
+ t.SetString(string(saveXMLData))
+ case reflect.Slice:
+ t.Set(reflect.ValueOf(saveXMLData))
+ }
+
+ return nil
+}
+
+func copyValue(dst reflect.Value, src []byte) (err os.Error) {
// Helper functions for integer and unsigned integer conversions
var itmp int64
getInt64 := func() bool {
- itmp, err = strconv.Atoi64(string(data))
+ itmp, err = strconv.Atoi64(string(src))
// TODO: should check sizes
return err == nil
}
var utmp uint64
getUint64 := func() bool {
- utmp, err = strconv.Atoui64(string(data))
+ utmp, err = strconv.Atoui64(string(src))
// TODO: check for overflow?
return err == nil
}
var ftmp float64
getFloat64 := func() bool {
- ftmp, err = strconv.Atof64(string(data))
+ ftmp, err = strconv.Atof64(string(src))
// TODO: check for overflow?
return err == nil
}
// Save accumulated data and comments
- switch t := saveData; t.Kind() {
+ switch t := dst; t.Kind() {
case reflect.Invalid:
// Probably a comment, handled below
default:
- return os.ErrorString("cannot happen: unknown type " + t.Type().String())
+ return os.NewError("cannot happen: unknown type " + t.Type().String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if !getInt64() {
return err
@@ -497,31 +526,16 @@ Loop:
}
t.SetFloat(ftmp)
case reflect.Bool:
- value, err := strconv.Atob(strings.TrimSpace(string(data)))
+ value, err := strconv.Atob(strings.TrimSpace(string(src)))
if err != nil {
return err
}
t.SetBool(value)
case reflect.String:
- t.SetString(string(data))
+ t.SetString(string(src))
case reflect.Slice:
- t.Set(reflect.ValueOf(data))
+ t.Set(reflect.ValueOf(src))
}
-
- switch t := saveComment; t.Kind() {
- case reflect.String:
- t.SetString(string(comment))
- case reflect.Slice:
- t.Set(reflect.ValueOf(comment))
- }
-
- switch t := saveXML; t.Kind() {
- case reflect.String:
- t.SetString(string(saveXMLData))
- case reflect.Slice:
- t.Set(reflect.ValueOf(saveXMLData))
- }
-
return nil
}
@@ -561,7 +575,7 @@ func tagError(sv reflect.Value, idx1 []int, idx2 []int) os.Error {
t := sv.Type()
f1 := t.FieldByIndex(idx1)
f2 := t.FieldByIndex(idx2)
- return &TagPathError{t, f1.Name, f1.Tag, f2.Name, f2.Tag}
+ return &TagPathError{t, f1.Name, f1.Tag.Get("xml"), f2.Name, f2.Tag.Get("xml")}
}
// unmarshalPaths walks down an XML structure looking for
diff --git a/libgo/go/xml/read_test.go b/libgo/go/xml/read_test.go
index d4ae370..2126da3 100644
--- a/libgo/go/xml/read_test.go
+++ b/libgo/go/xml/read_test.go
@@ -78,7 +78,7 @@ not being used from outside intra_region_diff.py.
</summary></entry></feed> `
type Feed struct {
- XMLName Name "http://www.w3.org/2005/Atom feed"
+ XMLName Name `xml:"http://www.w3.org/2005/Atom feed"`
Title string
Id string
Link []Link
@@ -97,20 +97,20 @@ type Entry struct {
}
type Link struct {
- Rel string "attr"
- Href string "attr"
+ Rel string `xml:"attr"`
+ Href string `xml:"attr"`
}
type Person struct {
Name string
URI string
Email string
- InnerXML string "innerxml"
+ InnerXML string `xml:"innerxml"`
}
type Text struct {
- Type string "attr"
- Body string "chardata"
+ Type string `xml:"attr"`
+ Body string `xml:"chardata"`
}
type Time string
@@ -255,18 +255,18 @@ type PathTestItem struct {
}
type PathTestA struct {
- Items []PathTestItem ">item1"
+ Items []PathTestItem `xml:">item1"`
Before, After string
}
type PathTestB struct {
- Other []PathTestItem "items>Item1"
+ Other []PathTestItem `xml:"items>Item1"`
Before, After string
}
type PathTestC struct {
- Values1 []string "items>item1>value"
- Values2 []string "items>item2>value"
+ Values1 []string `xml:"items>item1>value"`
+ Values2 []string `xml:"items>item2>value"`
Before, After string
}
@@ -275,7 +275,7 @@ type PathTestSet struct {
}
type PathTestD struct {
- Other PathTestSet "items>"
+ Other PathTestSet `xml:"items>"`
Before, After string
}
@@ -299,15 +299,15 @@ func TestUnmarshalPaths(t *testing.T) {
}
type BadPathTestA struct {
- First string "items>item1"
- Other string "items>item2"
- Second string "items>"
+ First string `xml:"items>item1"`
+ Other string `xml:"items>item2"`
+ Second string `xml:"items>"`
}
type BadPathTestB struct {
- Other string "items>item2>value"
- First string "items>item1"
- Second string "items>item1>value"
+ Other string `xml:"items>item2>value"`
+ First string `xml:"items>item1"`
+ Second string `xml:"items>item1>value"`
}
var badPathTests = []struct {
@@ -325,3 +325,47 @@ func TestUnmarshalBadPaths(t *testing.T) {
}
}
}
+
+func TestUnmarshalAttrs(t *testing.T) {
+ var f AttrTest
+ if err := Unmarshal(StringReader(attrString), &f); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if !reflect.DeepEqual(f, attrStruct) {
+ t.Fatalf("have %#v\nwant %#v", f, attrStruct)
+ }
+}
+
+type AttrTest struct {
+ Test1 Test1
+ Test2 Test2
+}
+
+type Test1 struct {
+ Int int `xml:"attr"`
+ Float float64 `xml:"attr"`
+ Uint8 uint8 `xml:"attr"`
+}
+
+type Test2 struct {
+ Bool bool `xml:"attr"`
+}
+
+const attrString = `
+<?xml version="1.0" charset="utf-8"?>
+<attrtest>
+ <test1 int="8" float="23.5" uint8="255"/>
+ <test2 bool="true"/>
+</attrtest>
+`
+
+var attrStruct = AttrTest{
+ Test1: Test1{
+ Int: 8,
+ Float: 23.5,
+ Uint8: 255,
+ },
+ Test2: Test2{
+ Bool: true,
+ },
+}
diff --git a/libgo/go/xml/xml.go b/libgo/go/xml/xml.go
index 42d8b98..e7ba44e 100644
--- a/libgo/go/xml/xml.go
+++ b/libgo/go/xml/xml.go
@@ -416,7 +416,6 @@ func (p *Parser) autoClose(t Token) (Token, bool) {
return nil, false
}
-
// RawToken is like Token but does not verify that
// start and end elements match and does not translate
// name space prefixes to their corresponding URLs.
@@ -659,17 +658,22 @@ func (p *Parser) RawToken() (Token, os.Error) {
return nil, p.err
}
if b != '=' {
- p.err = p.syntaxError("attribute name without = in element")
- return nil, p.err
- }
- p.space()
- data := p.attrval()
- if data == nil {
- return nil, p.err
+ if p.Strict {
+ p.err = p.syntaxError("attribute name without = in element")
+ return nil, p.err
+ } else {
+ p.ungetc(b)
+ a.Value = a.Name.Local
+ }
+ } else {
+ p.space()
+ data := p.attrval()
+ if data == nil {
+ return nil, p.err
+ }
+ a.Value = string(data)
}
- a.Value = string(data)
}
-
if empty {
p.needClose = true
p.toClose = name
@@ -1028,312 +1032,316 @@ func isNameByte(c byte) bool {
// and then reformatting. First corresponds to (Letter | '_' | ':')
// and second corresponds to NameChar.
-var first = []unicode.Range{
- {0x003A, 0x003A, 1},
- {0x0041, 0x005A, 1},
- {0x005F, 0x005F, 1},
- {0x0061, 0x007A, 1},
- {0x00C0, 0x00D6, 1},
- {0x00D8, 0x00F6, 1},
- {0x00F8, 0x00FF, 1},
- {0x0100, 0x0131, 1},
- {0x0134, 0x013E, 1},
- {0x0141, 0x0148, 1},
- {0x014A, 0x017E, 1},
- {0x0180, 0x01C3, 1},
- {0x01CD, 0x01F0, 1},
- {0x01F4, 0x01F5, 1},
- {0x01FA, 0x0217, 1},
- {0x0250, 0x02A8, 1},
- {0x02BB, 0x02C1, 1},
- {0x0386, 0x0386, 1},
- {0x0388, 0x038A, 1},
- {0x038C, 0x038C, 1},
- {0x038E, 0x03A1, 1},
- {0x03A3, 0x03CE, 1},
- {0x03D0, 0x03D6, 1},
- {0x03DA, 0x03E0, 2},
- {0x03E2, 0x03F3, 1},
- {0x0401, 0x040C, 1},
- {0x040E, 0x044F, 1},
- {0x0451, 0x045C, 1},
- {0x045E, 0x0481, 1},
- {0x0490, 0x04C4, 1},
- {0x04C7, 0x04C8, 1},
- {0x04CB, 0x04CC, 1},
- {0x04D0, 0x04EB, 1},
- {0x04EE, 0x04F5, 1},
- {0x04F8, 0x04F9, 1},
- {0x0531, 0x0556, 1},
- {0x0559, 0x0559, 1},
- {0x0561, 0x0586, 1},
- {0x05D0, 0x05EA, 1},
- {0x05F0, 0x05F2, 1},
- {0x0621, 0x063A, 1},
- {0x0641, 0x064A, 1},
- {0x0671, 0x06B7, 1},
- {0x06BA, 0x06BE, 1},
- {0x06C0, 0x06CE, 1},
- {0x06D0, 0x06D3, 1},
- {0x06D5, 0x06D5, 1},
- {0x06E5, 0x06E6, 1},
- {0x0905, 0x0939, 1},
- {0x093D, 0x093D, 1},
- {0x0958, 0x0961, 1},
- {0x0985, 0x098C, 1},
- {0x098F, 0x0990, 1},
- {0x0993, 0x09A8, 1},
- {0x09AA, 0x09B0, 1},
- {0x09B2, 0x09B2, 1},
- {0x09B6, 0x09B9, 1},
- {0x09DC, 0x09DD, 1},
- {0x09DF, 0x09E1, 1},
- {0x09F0, 0x09F1, 1},
- {0x0A05, 0x0A0A, 1},
- {0x0A0F, 0x0A10, 1},
- {0x0A13, 0x0A28, 1},
- {0x0A2A, 0x0A30, 1},
- {0x0A32, 0x0A33, 1},
- {0x0A35, 0x0A36, 1},
- {0x0A38, 0x0A39, 1},
- {0x0A59, 0x0A5C, 1},
- {0x0A5E, 0x0A5E, 1},
- {0x0A72, 0x0A74, 1},
- {0x0A85, 0x0A8B, 1},
- {0x0A8D, 0x0A8D, 1},
- {0x0A8F, 0x0A91, 1},
- {0x0A93, 0x0AA8, 1},
- {0x0AAA, 0x0AB0, 1},
- {0x0AB2, 0x0AB3, 1},
- {0x0AB5, 0x0AB9, 1},
- {0x0ABD, 0x0AE0, 0x23},
- {0x0B05, 0x0B0C, 1},
- {0x0B0F, 0x0B10, 1},
- {0x0B13, 0x0B28, 1},
- {0x0B2A, 0x0B30, 1},
- {0x0B32, 0x0B33, 1},
- {0x0B36, 0x0B39, 1},
- {0x0B3D, 0x0B3D, 1},
- {0x0B5C, 0x0B5D, 1},
- {0x0B5F, 0x0B61, 1},
- {0x0B85, 0x0B8A, 1},
- {0x0B8E, 0x0B90, 1},
- {0x0B92, 0x0B95, 1},
- {0x0B99, 0x0B9A, 1},
- {0x0B9C, 0x0B9C, 1},
- {0x0B9E, 0x0B9F, 1},
- {0x0BA3, 0x0BA4, 1},
- {0x0BA8, 0x0BAA, 1},
- {0x0BAE, 0x0BB5, 1},
- {0x0BB7, 0x0BB9, 1},
- {0x0C05, 0x0C0C, 1},
- {0x0C0E, 0x0C10, 1},
- {0x0C12, 0x0C28, 1},
- {0x0C2A, 0x0C33, 1},
- {0x0C35, 0x0C39, 1},
- {0x0C60, 0x0C61, 1},
- {0x0C85, 0x0C8C, 1},
- {0x0C8E, 0x0C90, 1},
- {0x0C92, 0x0CA8, 1},
- {0x0CAA, 0x0CB3, 1},
- {0x0CB5, 0x0CB9, 1},
- {0x0CDE, 0x0CDE, 1},
- {0x0CE0, 0x0CE1, 1},
- {0x0D05, 0x0D0C, 1},
- {0x0D0E, 0x0D10, 1},
- {0x0D12, 0x0D28, 1},
- {0x0D2A, 0x0D39, 1},
- {0x0D60, 0x0D61, 1},
- {0x0E01, 0x0E2E, 1},
- {0x0E30, 0x0E30, 1},
- {0x0E32, 0x0E33, 1},
- {0x0E40, 0x0E45, 1},
- {0x0E81, 0x0E82, 1},
- {0x0E84, 0x0E84, 1},
- {0x0E87, 0x0E88, 1},
- {0x0E8A, 0x0E8D, 3},
- {0x0E94, 0x0E97, 1},
- {0x0E99, 0x0E9F, 1},
- {0x0EA1, 0x0EA3, 1},
- {0x0EA5, 0x0EA7, 2},
- {0x0EAA, 0x0EAB, 1},
- {0x0EAD, 0x0EAE, 1},
- {0x0EB0, 0x0EB0, 1},
- {0x0EB2, 0x0EB3, 1},
- {0x0EBD, 0x0EBD, 1},
- {0x0EC0, 0x0EC4, 1},
- {0x0F40, 0x0F47, 1},
- {0x0F49, 0x0F69, 1},
- {0x10A0, 0x10C5, 1},
- {0x10D0, 0x10F6, 1},
- {0x1100, 0x1100, 1},
- {0x1102, 0x1103, 1},
- {0x1105, 0x1107, 1},
- {0x1109, 0x1109, 1},
- {0x110B, 0x110C, 1},
- {0x110E, 0x1112, 1},
- {0x113C, 0x1140, 2},
- {0x114C, 0x1150, 2},
- {0x1154, 0x1155, 1},
- {0x1159, 0x1159, 1},
- {0x115F, 0x1161, 1},
- {0x1163, 0x1169, 2},
- {0x116D, 0x116E, 1},
- {0x1172, 0x1173, 1},
- {0x1175, 0x119E, 0x119E - 0x1175},
- {0x11A8, 0x11AB, 0x11AB - 0x11A8},
- {0x11AE, 0x11AF, 1},
- {0x11B7, 0x11B8, 1},
- {0x11BA, 0x11BA, 1},
- {0x11BC, 0x11C2, 1},
- {0x11EB, 0x11F0, 0x11F0 - 0x11EB},
- {0x11F9, 0x11F9, 1},
- {0x1E00, 0x1E9B, 1},
- {0x1EA0, 0x1EF9, 1},
- {0x1F00, 0x1F15, 1},
- {0x1F18, 0x1F1D, 1},
- {0x1F20, 0x1F45, 1},
- {0x1F48, 0x1F4D, 1},
- {0x1F50, 0x1F57, 1},
- {0x1F59, 0x1F5B, 0x1F5B - 0x1F59},
- {0x1F5D, 0x1F5D, 1},
- {0x1F5F, 0x1F7D, 1},
- {0x1F80, 0x1FB4, 1},
- {0x1FB6, 0x1FBC, 1},
- {0x1FBE, 0x1FBE, 1},
- {0x1FC2, 0x1FC4, 1},
- {0x1FC6, 0x1FCC, 1},
- {0x1FD0, 0x1FD3, 1},
- {0x1FD6, 0x1FDB, 1},
- {0x1FE0, 0x1FEC, 1},
- {0x1FF2, 0x1FF4, 1},
- {0x1FF6, 0x1FFC, 1},
- {0x2126, 0x2126, 1},
- {0x212A, 0x212B, 1},
- {0x212E, 0x212E, 1},
- {0x2180, 0x2182, 1},
- {0x3007, 0x3007, 1},
- {0x3021, 0x3029, 1},
- {0x3041, 0x3094, 1},
- {0x30A1, 0x30FA, 1},
- {0x3105, 0x312C, 1},
- {0x4E00, 0x9FA5, 1},
- {0xAC00, 0xD7A3, 1},
+var first = &unicode.RangeTable{
+ R16: []unicode.Range16{
+ {0x003A, 0x003A, 1},
+ {0x0041, 0x005A, 1},
+ {0x005F, 0x005F, 1},
+ {0x0061, 0x007A, 1},
+ {0x00C0, 0x00D6, 1},
+ {0x00D8, 0x00F6, 1},
+ {0x00F8, 0x00FF, 1},
+ {0x0100, 0x0131, 1},
+ {0x0134, 0x013E, 1},
+ {0x0141, 0x0148, 1},
+ {0x014A, 0x017E, 1},
+ {0x0180, 0x01C3, 1},
+ {0x01CD, 0x01F0, 1},
+ {0x01F4, 0x01F5, 1},
+ {0x01FA, 0x0217, 1},
+ {0x0250, 0x02A8, 1},
+ {0x02BB, 0x02C1, 1},
+ {0x0386, 0x0386, 1},
+ {0x0388, 0x038A, 1},
+ {0x038C, 0x038C, 1},
+ {0x038E, 0x03A1, 1},
+ {0x03A3, 0x03CE, 1},
+ {0x03D0, 0x03D6, 1},
+ {0x03DA, 0x03E0, 2},
+ {0x03E2, 0x03F3, 1},
+ {0x0401, 0x040C, 1},
+ {0x040E, 0x044F, 1},
+ {0x0451, 0x045C, 1},
+ {0x045E, 0x0481, 1},
+ {0x0490, 0x04C4, 1},
+ {0x04C7, 0x04C8, 1},
+ {0x04CB, 0x04CC, 1},
+ {0x04D0, 0x04EB, 1},
+ {0x04EE, 0x04F5, 1},
+ {0x04F8, 0x04F9, 1},
+ {0x0531, 0x0556, 1},
+ {0x0559, 0x0559, 1},
+ {0x0561, 0x0586, 1},
+ {0x05D0, 0x05EA, 1},
+ {0x05F0, 0x05F2, 1},
+ {0x0621, 0x063A, 1},
+ {0x0641, 0x064A, 1},
+ {0x0671, 0x06B7, 1},
+ {0x06BA, 0x06BE, 1},
+ {0x06C0, 0x06CE, 1},
+ {0x06D0, 0x06D3, 1},
+ {0x06D5, 0x06D5, 1},
+ {0x06E5, 0x06E6, 1},
+ {0x0905, 0x0939, 1},
+ {0x093D, 0x093D, 1},
+ {0x0958, 0x0961, 1},
+ {0x0985, 0x098C, 1},
+ {0x098F, 0x0990, 1},
+ {0x0993, 0x09A8, 1},
+ {0x09AA, 0x09B0, 1},
+ {0x09B2, 0x09B2, 1},
+ {0x09B6, 0x09B9, 1},
+ {0x09DC, 0x09DD, 1},
+ {0x09DF, 0x09E1, 1},
+ {0x09F0, 0x09F1, 1},
+ {0x0A05, 0x0A0A, 1},
+ {0x0A0F, 0x0A10, 1},
+ {0x0A13, 0x0A28, 1},
+ {0x0A2A, 0x0A30, 1},
+ {0x0A32, 0x0A33, 1},
+ {0x0A35, 0x0A36, 1},
+ {0x0A38, 0x0A39, 1},
+ {0x0A59, 0x0A5C, 1},
+ {0x0A5E, 0x0A5E, 1},
+ {0x0A72, 0x0A74, 1},
+ {0x0A85, 0x0A8B, 1},
+ {0x0A8D, 0x0A8D, 1},
+ {0x0A8F, 0x0A91, 1},
+ {0x0A93, 0x0AA8, 1},
+ {0x0AAA, 0x0AB0, 1},
+ {0x0AB2, 0x0AB3, 1},
+ {0x0AB5, 0x0AB9, 1},
+ {0x0ABD, 0x0AE0, 0x23},
+ {0x0B05, 0x0B0C, 1},
+ {0x0B0F, 0x0B10, 1},
+ {0x0B13, 0x0B28, 1},
+ {0x0B2A, 0x0B30, 1},
+ {0x0B32, 0x0B33, 1},
+ {0x0B36, 0x0B39, 1},
+ {0x0B3D, 0x0B3D, 1},
+ {0x0B5C, 0x0B5D, 1},
+ {0x0B5F, 0x0B61, 1},
+ {0x0B85, 0x0B8A, 1},
+ {0x0B8E, 0x0B90, 1},
+ {0x0B92, 0x0B95, 1},
+ {0x0B99, 0x0B9A, 1},
+ {0x0B9C, 0x0B9C, 1},
+ {0x0B9E, 0x0B9F, 1},
+ {0x0BA3, 0x0BA4, 1},
+ {0x0BA8, 0x0BAA, 1},
+ {0x0BAE, 0x0BB5, 1},
+ {0x0BB7, 0x0BB9, 1},
+ {0x0C05, 0x0C0C, 1},
+ {0x0C0E, 0x0C10, 1},
+ {0x0C12, 0x0C28, 1},
+ {0x0C2A, 0x0C33, 1},
+ {0x0C35, 0x0C39, 1},
+ {0x0C60, 0x0C61, 1},
+ {0x0C85, 0x0C8C, 1},
+ {0x0C8E, 0x0C90, 1},
+ {0x0C92, 0x0CA8, 1},
+ {0x0CAA, 0x0CB3, 1},
+ {0x0CB5, 0x0CB9, 1},
+ {0x0CDE, 0x0CDE, 1},
+ {0x0CE0, 0x0CE1, 1},
+ {0x0D05, 0x0D0C, 1},
+ {0x0D0E, 0x0D10, 1},
+ {0x0D12, 0x0D28, 1},
+ {0x0D2A, 0x0D39, 1},
+ {0x0D60, 0x0D61, 1},
+ {0x0E01, 0x0E2E, 1},
+ {0x0E30, 0x0E30, 1},
+ {0x0E32, 0x0E33, 1},
+ {0x0E40, 0x0E45, 1},
+ {0x0E81, 0x0E82, 1},
+ {0x0E84, 0x0E84, 1},
+ {0x0E87, 0x0E88, 1},
+ {0x0E8A, 0x0E8D, 3},
+ {0x0E94, 0x0E97, 1},
+ {0x0E99, 0x0E9F, 1},
+ {0x0EA1, 0x0EA3, 1},
+ {0x0EA5, 0x0EA7, 2},
+ {0x0EAA, 0x0EAB, 1},
+ {0x0EAD, 0x0EAE, 1},
+ {0x0EB0, 0x0EB0, 1},
+ {0x0EB2, 0x0EB3, 1},
+ {0x0EBD, 0x0EBD, 1},
+ {0x0EC0, 0x0EC4, 1},
+ {0x0F40, 0x0F47, 1},
+ {0x0F49, 0x0F69, 1},
+ {0x10A0, 0x10C5, 1},
+ {0x10D0, 0x10F6, 1},
+ {0x1100, 0x1100, 1},
+ {0x1102, 0x1103, 1},
+ {0x1105, 0x1107, 1},
+ {0x1109, 0x1109, 1},
+ {0x110B, 0x110C, 1},
+ {0x110E, 0x1112, 1},
+ {0x113C, 0x1140, 2},
+ {0x114C, 0x1150, 2},
+ {0x1154, 0x1155, 1},
+ {0x1159, 0x1159, 1},
+ {0x115F, 0x1161, 1},
+ {0x1163, 0x1169, 2},
+ {0x116D, 0x116E, 1},
+ {0x1172, 0x1173, 1},
+ {0x1175, 0x119E, 0x119E - 0x1175},
+ {0x11A8, 0x11AB, 0x11AB - 0x11A8},
+ {0x11AE, 0x11AF, 1},
+ {0x11B7, 0x11B8, 1},
+ {0x11BA, 0x11BA, 1},
+ {0x11BC, 0x11C2, 1},
+ {0x11EB, 0x11F0, 0x11F0 - 0x11EB},
+ {0x11F9, 0x11F9, 1},
+ {0x1E00, 0x1E9B, 1},
+ {0x1EA0, 0x1EF9, 1},
+ {0x1F00, 0x1F15, 1},
+ {0x1F18, 0x1F1D, 1},
+ {0x1F20, 0x1F45, 1},
+ {0x1F48, 0x1F4D, 1},
+ {0x1F50, 0x1F57, 1},
+ {0x1F59, 0x1F5B, 0x1F5B - 0x1F59},
+ {0x1F5D, 0x1F5D, 1},
+ {0x1F5F, 0x1F7D, 1},
+ {0x1F80, 0x1FB4, 1},
+ {0x1FB6, 0x1FBC, 1},
+ {0x1FBE, 0x1FBE, 1},
+ {0x1FC2, 0x1FC4, 1},
+ {0x1FC6, 0x1FCC, 1},
+ {0x1FD0, 0x1FD3, 1},
+ {0x1FD6, 0x1FDB, 1},
+ {0x1FE0, 0x1FEC, 1},
+ {0x1FF2, 0x1FF4, 1},
+ {0x1FF6, 0x1FFC, 1},
+ {0x2126, 0x2126, 1},
+ {0x212A, 0x212B, 1},
+ {0x212E, 0x212E, 1},
+ {0x2180, 0x2182, 1},
+ {0x3007, 0x3007, 1},
+ {0x3021, 0x3029, 1},
+ {0x3041, 0x3094, 1},
+ {0x30A1, 0x30FA, 1},
+ {0x3105, 0x312C, 1},
+ {0x4E00, 0x9FA5, 1},
+ {0xAC00, 0xD7A3, 1},
+ },
}
-var second = []unicode.Range{
- {0x002D, 0x002E, 1},
- {0x0030, 0x0039, 1},
- {0x00B7, 0x00B7, 1},
- {0x02D0, 0x02D1, 1},
- {0x0300, 0x0345, 1},
- {0x0360, 0x0361, 1},
- {0x0387, 0x0387, 1},
- {0x0483, 0x0486, 1},
- {0x0591, 0x05A1, 1},
- {0x05A3, 0x05B9, 1},
- {0x05BB, 0x05BD, 1},
- {0x05BF, 0x05BF, 1},
- {0x05C1, 0x05C2, 1},
- {0x05C4, 0x0640, 0x0640 - 0x05C4},
- {0x064B, 0x0652, 1},
- {0x0660, 0x0669, 1},
- {0x0670, 0x0670, 1},
- {0x06D6, 0x06DC, 1},
- {0x06DD, 0x06DF, 1},
- {0x06E0, 0x06E4, 1},
- {0x06E7, 0x06E8, 1},
- {0x06EA, 0x06ED, 1},
- {0x06F0, 0x06F9, 1},
- {0x0901, 0x0903, 1},
- {0x093C, 0x093C, 1},
- {0x093E, 0x094C, 1},
- {0x094D, 0x094D, 1},
- {0x0951, 0x0954, 1},
- {0x0962, 0x0963, 1},
- {0x0966, 0x096F, 1},
- {0x0981, 0x0983, 1},
- {0x09BC, 0x09BC, 1},
- {0x09BE, 0x09BF, 1},
- {0x09C0, 0x09C4, 1},
- {0x09C7, 0x09C8, 1},
- {0x09CB, 0x09CD, 1},
- {0x09D7, 0x09D7, 1},
- {0x09E2, 0x09E3, 1},
- {0x09E6, 0x09EF, 1},
- {0x0A02, 0x0A3C, 0x3A},
- {0x0A3E, 0x0A3F, 1},
- {0x0A40, 0x0A42, 1},
- {0x0A47, 0x0A48, 1},
- {0x0A4B, 0x0A4D, 1},
- {0x0A66, 0x0A6F, 1},
- {0x0A70, 0x0A71, 1},
- {0x0A81, 0x0A83, 1},
- {0x0ABC, 0x0ABC, 1},
- {0x0ABE, 0x0AC5, 1},
- {0x0AC7, 0x0AC9, 1},
- {0x0ACB, 0x0ACD, 1},
- {0x0AE6, 0x0AEF, 1},
- {0x0B01, 0x0B03, 1},
- {0x0B3C, 0x0B3C, 1},
- {0x0B3E, 0x0B43, 1},
- {0x0B47, 0x0B48, 1},
- {0x0B4B, 0x0B4D, 1},
- {0x0B56, 0x0B57, 1},
- {0x0B66, 0x0B6F, 1},
- {0x0B82, 0x0B83, 1},
- {0x0BBE, 0x0BC2, 1},
- {0x0BC6, 0x0BC8, 1},
- {0x0BCA, 0x0BCD, 1},
- {0x0BD7, 0x0BD7, 1},
- {0x0BE7, 0x0BEF, 1},
- {0x0C01, 0x0C03, 1},
- {0x0C3E, 0x0C44, 1},
- {0x0C46, 0x0C48, 1},
- {0x0C4A, 0x0C4D, 1},
- {0x0C55, 0x0C56, 1},
- {0x0C66, 0x0C6F, 1},
- {0x0C82, 0x0C83, 1},
- {0x0CBE, 0x0CC4, 1},
- {0x0CC6, 0x0CC8, 1},
- {0x0CCA, 0x0CCD, 1},
- {0x0CD5, 0x0CD6, 1},
- {0x0CE6, 0x0CEF, 1},
- {0x0D02, 0x0D03, 1},
- {0x0D3E, 0x0D43, 1},
- {0x0D46, 0x0D48, 1},
- {0x0D4A, 0x0D4D, 1},
- {0x0D57, 0x0D57, 1},
- {0x0D66, 0x0D6F, 1},
- {0x0E31, 0x0E31, 1},
- {0x0E34, 0x0E3A, 1},
- {0x0E46, 0x0E46, 1},
- {0x0E47, 0x0E4E, 1},
- {0x0E50, 0x0E59, 1},
- {0x0EB1, 0x0EB1, 1},
- {0x0EB4, 0x0EB9, 1},
- {0x0EBB, 0x0EBC, 1},
- {0x0EC6, 0x0EC6, 1},
- {0x0EC8, 0x0ECD, 1},
- {0x0ED0, 0x0ED9, 1},
- {0x0F18, 0x0F19, 1},
- {0x0F20, 0x0F29, 1},
- {0x0F35, 0x0F39, 2},
- {0x0F3E, 0x0F3F, 1},
- {0x0F71, 0x0F84, 1},
- {0x0F86, 0x0F8B, 1},
- {0x0F90, 0x0F95, 1},
- {0x0F97, 0x0F97, 1},
- {0x0F99, 0x0FAD, 1},
- {0x0FB1, 0x0FB7, 1},
- {0x0FB9, 0x0FB9, 1},
- {0x20D0, 0x20DC, 1},
- {0x20E1, 0x3005, 0x3005 - 0x20E1},
- {0x302A, 0x302F, 1},
- {0x3031, 0x3035, 1},
- {0x3099, 0x309A, 1},
- {0x309D, 0x309E, 1},
- {0x30FC, 0x30FE, 1},
+var second = &unicode.RangeTable{
+ R16: []unicode.Range16{
+ {0x002D, 0x002E, 1},
+ {0x0030, 0x0039, 1},
+ {0x00B7, 0x00B7, 1},
+ {0x02D0, 0x02D1, 1},
+ {0x0300, 0x0345, 1},
+ {0x0360, 0x0361, 1},
+ {0x0387, 0x0387, 1},
+ {0x0483, 0x0486, 1},
+ {0x0591, 0x05A1, 1},
+ {0x05A3, 0x05B9, 1},
+ {0x05BB, 0x05BD, 1},
+ {0x05BF, 0x05BF, 1},
+ {0x05C1, 0x05C2, 1},
+ {0x05C4, 0x0640, 0x0640 - 0x05C4},
+ {0x064B, 0x0652, 1},
+ {0x0660, 0x0669, 1},
+ {0x0670, 0x0670, 1},
+ {0x06D6, 0x06DC, 1},
+ {0x06DD, 0x06DF, 1},
+ {0x06E0, 0x06E4, 1},
+ {0x06E7, 0x06E8, 1},
+ {0x06EA, 0x06ED, 1},
+ {0x06F0, 0x06F9, 1},
+ {0x0901, 0x0903, 1},
+ {0x093C, 0x093C, 1},
+ {0x093E, 0x094C, 1},
+ {0x094D, 0x094D, 1},
+ {0x0951, 0x0954, 1},
+ {0x0962, 0x0963, 1},
+ {0x0966, 0x096F, 1},
+ {0x0981, 0x0983, 1},
+ {0x09BC, 0x09BC, 1},
+ {0x09BE, 0x09BF, 1},
+ {0x09C0, 0x09C4, 1},
+ {0x09C7, 0x09C8, 1},
+ {0x09CB, 0x09CD, 1},
+ {0x09D7, 0x09D7, 1},
+ {0x09E2, 0x09E3, 1},
+ {0x09E6, 0x09EF, 1},
+ {0x0A02, 0x0A3C, 0x3A},
+ {0x0A3E, 0x0A3F, 1},
+ {0x0A40, 0x0A42, 1},
+ {0x0A47, 0x0A48, 1},
+ {0x0A4B, 0x0A4D, 1},
+ {0x0A66, 0x0A6F, 1},
+ {0x0A70, 0x0A71, 1},
+ {0x0A81, 0x0A83, 1},
+ {0x0ABC, 0x0ABC, 1},
+ {0x0ABE, 0x0AC5, 1},
+ {0x0AC7, 0x0AC9, 1},
+ {0x0ACB, 0x0ACD, 1},
+ {0x0AE6, 0x0AEF, 1},
+ {0x0B01, 0x0B03, 1},
+ {0x0B3C, 0x0B3C, 1},
+ {0x0B3E, 0x0B43, 1},
+ {0x0B47, 0x0B48, 1},
+ {0x0B4B, 0x0B4D, 1},
+ {0x0B56, 0x0B57, 1},
+ {0x0B66, 0x0B6F, 1},
+ {0x0B82, 0x0B83, 1},
+ {0x0BBE, 0x0BC2, 1},
+ {0x0BC6, 0x0BC8, 1},
+ {0x0BCA, 0x0BCD, 1},
+ {0x0BD7, 0x0BD7, 1},
+ {0x0BE7, 0x0BEF, 1},
+ {0x0C01, 0x0C03, 1},
+ {0x0C3E, 0x0C44, 1},
+ {0x0C46, 0x0C48, 1},
+ {0x0C4A, 0x0C4D, 1},
+ {0x0C55, 0x0C56, 1},
+ {0x0C66, 0x0C6F, 1},
+ {0x0C82, 0x0C83, 1},
+ {0x0CBE, 0x0CC4, 1},
+ {0x0CC6, 0x0CC8, 1},
+ {0x0CCA, 0x0CCD, 1},
+ {0x0CD5, 0x0CD6, 1},
+ {0x0CE6, 0x0CEF, 1},
+ {0x0D02, 0x0D03, 1},
+ {0x0D3E, 0x0D43, 1},
+ {0x0D46, 0x0D48, 1},
+ {0x0D4A, 0x0D4D, 1},
+ {0x0D57, 0x0D57, 1},
+ {0x0D66, 0x0D6F, 1},
+ {0x0E31, 0x0E31, 1},
+ {0x0E34, 0x0E3A, 1},
+ {0x0E46, 0x0E46, 1},
+ {0x0E47, 0x0E4E, 1},
+ {0x0E50, 0x0E59, 1},
+ {0x0EB1, 0x0EB1, 1},
+ {0x0EB4, 0x0EB9, 1},
+ {0x0EBB, 0x0EBC, 1},
+ {0x0EC6, 0x0EC6, 1},
+ {0x0EC8, 0x0ECD, 1},
+ {0x0ED0, 0x0ED9, 1},
+ {0x0F18, 0x0F19, 1},
+ {0x0F20, 0x0F29, 1},
+ {0x0F35, 0x0F39, 2},
+ {0x0F3E, 0x0F3F, 1},
+ {0x0F71, 0x0F84, 1},
+ {0x0F86, 0x0F8B, 1},
+ {0x0F90, 0x0F95, 1},
+ {0x0F97, 0x0F97, 1},
+ {0x0F99, 0x0FAD, 1},
+ {0x0FB1, 0x0FB7, 1},
+ {0x0FB9, 0x0FB9, 1},
+ {0x20D0, 0x20DC, 1},
+ {0x20E1, 0x3005, 0x3005 - 0x20E1},
+ {0x302A, 0x302F, 1},
+ {0x3031, 0x3035, 1},
+ {0x3099, 0x309A, 1},
+ {0x309D, 0x309E, 1},
+ {0x30FC, 0x30FE, 1},
+ },
}
// HTMLEntity is an entity map containing translations for the
diff --git a/libgo/go/xml/xml_test.go b/libgo/go/xml/xml_test.go
index 4e51cd5..6407624 100644
--- a/libgo/go/xml/xml_test.go
+++ b/libgo/go/xml/xml_test.go
@@ -445,6 +445,33 @@ func TestUnquotedAttrs(t *testing.T) {
}
}
+func TestValuelessAttrs(t *testing.T) {
+ tests := [][3]string{
+ {"<p nowrap>", "p", "nowrap"},
+ {"<p nowrap >", "p", "nowrap"},
+ {"<input checked/>", "input", "checked"},
+ {"<input checked />", "input", "checked"},
+ }
+ for _, test := range tests {
+ p := NewParser(StringReader(test[0]))
+ p.Strict = false
+ token, err := p.Token()
+ if _, ok := err.(*SyntaxError); ok {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if token.(StartElement).Name.Local != test[1] {
+ t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
+ }
+ attr := token.(StartElement).Attr[0]
+ if attr.Value != test[2] {
+ t.Errorf("Unexpected attribute value: %v", attr.Value)
+ }
+ if attr.Name.Local != test[2] {
+ t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
+ }
+ }
+}
+
func TestCopyTokenCharData(t *testing.T) {
data := []byte("same data")
var tok1 Token = CharData(data)
@@ -519,7 +546,6 @@ func TestEntityInsideCDATA(t *testing.T) {
}
}
-
// The last three tests (respectively one for characters in attribute
// names and two for character entities) pass not because of code
// changed for issue 1259, but instead pass with the given messages
@@ -540,7 +566,6 @@ var characterTests = []struct {
{"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &;"},
}
-
func TestDisallowedCharacters(t *testing.T) {
for i, tt := range characterTests {