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
5f77bf8b
Commit
5f77bf8b
authored
Jun 14, 2011
by
Maxim Ushakov
Committed by
Russ Cox
Jun 14, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
xml: handle non-string attribute fields
R=kevlar, rsc CC=golang-dev
https://golang.org/cl/4528114
parent
c195cc8d
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
92 additions
and
35 deletions
+92
-35
read.go
src/pkg/xml/read.go
+48
-35
read_test.go
src/pkg/xml/read_test.go
+44
-0
No files found.
src/pkg/xml/read.go
View file @
5f77bf8b
...
@@ -106,6 +106,11 @@ import (
...
@@ -106,6 +106,11 @@ import (
// The struct field may have type []byte or string.
// The struct field may have type []byte or string.
// If there is no such field, the character data is discarded.
// 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
// * 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 struct field tag formatted as "a>b>c", unmarshal
// will descend into the XML structure looking for elements with the
// will descend into the XML structure looking for elements with the
...
@@ -120,17 +125,22 @@ import (
...
@@ -120,17 +125,22 @@ import (
// maps the sub-element to that struct field.
// maps the sub-element to that struct field.
//
//
// Unmarshal maps an XML element to a string or []byte by saving the
// 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
// Unmarshal maps an XML element to a slice by extending the length
of
//
of
the slice and mapping the element to the newly created value.
// 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
// Unmarshal maps an XML element
or attribute value to a bool by
// value represented by the string.
//
setting it to the boolean
value represented by the string.
//
//
// Unmarshal maps an XML element to an integer or floating-point
// Unmarshal maps an XML element or attribute value to an integer or
// field by setting the field to the result of interpreting the string
// floating-point field by setting the field to the result of
// value in decimal. There is no check for overflow.
// interpreting the string value in decimal. There is no check for
// overflow.
//
//
// Unmarshal maps an XML element to an xml.Name by recording the
// Unmarshal maps an XML element to an xml.Name by recording the
// element name.
// element name.
...
@@ -323,9 +333,6 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
...
@@ -323,9 +333,6 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
switch
f
.
Tag
{
switch
f
.
Tag
{
case
"attr"
:
case
"attr"
:
strv
:=
sv
.
FieldByIndex
(
f
.
Index
)
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.
// Look for attribute.
val
:=
""
val
:=
""
k
:=
strings
.
ToLower
(
f
.
Name
)
k
:=
strings
.
ToLower
(
f
.
Name
)
...
@@ -335,7 +342,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
...
@@ -335,7 +342,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
break
break
}
}
}
}
strv
.
SetString
(
val
)
copyValue
(
strv
,
[]
byte
(
val
)
)
case
"comment"
:
case
"comment"
:
if
!
saveComment
.
IsValid
()
{
if
!
saveComment
.
IsValid
()
{
...
@@ -454,29 +461,50 @@ Loop:
...
@@ -454,29 +461,50 @@ 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
// Helper functions for integer and unsigned integer conversions
var
itmp
int64
var
itmp
int64
getInt64
:=
func
()
bool
{
getInt64
:=
func
()
bool
{
itmp
,
err
=
strconv
.
Atoi64
(
string
(
data
))
itmp
,
err
=
strconv
.
Atoi64
(
string
(
src
))
// TODO: should check sizes
// TODO: should check sizes
return
err
==
nil
return
err
==
nil
}
}
var
utmp
uint64
var
utmp
uint64
getUint64
:=
func
()
bool
{
getUint64
:=
func
()
bool
{
utmp
,
err
=
strconv
.
Atoui64
(
string
(
data
))
utmp
,
err
=
strconv
.
Atoui64
(
string
(
src
))
// TODO: check for overflow?
// TODO: check for overflow?
return
err
==
nil
return
err
==
nil
}
}
var
ftmp
float64
var
ftmp
float64
getFloat64
:=
func
()
bool
{
getFloat64
:=
func
()
bool
{
ftmp
,
err
=
strconv
.
Atof64
(
string
(
data
))
ftmp
,
err
=
strconv
.
Atof64
(
string
(
src
))
// TODO: check for overflow?
// TODO: check for overflow?
return
err
==
nil
return
err
==
nil
}
}
// Save accumulated data and comments
// Save accumulated data and comments
switch
t
:=
saveData
;
t
.
Kind
()
{
switch
t
:=
dst
;
t
.
Kind
()
{
case
reflect
.
Invalid
:
case
reflect
.
Invalid
:
// Probably a comment, handled below
// Probably a comment, handled below
default
:
default
:
...
@@ -497,31 +525,16 @@ Loop:
...
@@ -497,31 +525,16 @@ Loop:
}
}
t
.
SetFloat
(
ftmp
)
t
.
SetFloat
(
ftmp
)
case
reflect
.
Bool
:
case
reflect
.
Bool
:
value
,
err
:=
strconv
.
Atob
(
strings
.
TrimSpace
(
string
(
data
)))
value
,
err
:=
strconv
.
Atob
(
strings
.
TrimSpace
(
string
(
src
)))
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
t
.
SetBool
(
value
)
t
.
SetBool
(
value
)
case
reflect
.
String
:
case
reflect
.
String
:
t
.
SetString
(
string
(
data
))
t
.
SetString
(
string
(
src
))
case
reflect
.
Slice
:
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
return
nil
}
}
...
...
src/pkg/xml/read_test.go
View file @
5f77bf8b
...
@@ -325,3 +325,47 @@ func TestUnmarshalBadPaths(t *testing.T) {
...
@@ -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
\n
want %#v"
,
f
,
attrStruct
)
}
}
type
AttrTest
struct
{
Test1
Test1
Test2
Test2
}
type
Test1
struct
{
Int
int
"attr"
Float
float64
"attr"
Uint8
uint8
"attr"
}
type
Test2
struct
{
Bool
bool
"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
,
},
}
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