Guest User

Untitled

a guest
Apr 20th, 2018
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.82 KB | None | 0 0
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4.  
  5. package xml
  6.  
  7. import (
  8. "bytes"
  9. "encoding"
  10. "errors"
  11. "fmt"
  12. "reflect"
  13. "strconv"
  14. "strings"
  15. )
  16.  
  17. // BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
  18. // an XML element is an order-dependent collection of anonymous
  19. // values, while a data structure is an order-independent collection
  20. // of named values.
  21. // See package json for a textual representation more suitable
  22. // to data structures.
  23.  
  24. // Unmarshal parses the XML-encoded data and stores the result in
  25. // the value pointed to by v, which must be an arbitrary struct,
  26. // slice, or string. Well-formed data that does not fit into v is
  27. // discarded.
  28. //
  29. // Because Unmarshal uses the reflect package, it can only assign
  30. // to exported (upper case) fields. Unmarshal uses a case-sensitive
  31. // comparison to match XML element names to tag values and struct
  32. // field names.
  33. //
  34. // Unmarshal maps an XML element to a struct using the following rules.
  35. // In the rules, the tag of a field refers to the value associated with the
  36. // key 'xml' in the struct field's tag (see the example above).
  37. //
  38. // * If the struct has a field of type []byte or string with tag
  39. // ",innerxml", Unmarshal accumulates the raw XML nested inside the
  40. // element in that field. The rest of the rules still apply.
  41. //
  42. // * If the struct has a field named XMLName of type Name,
  43. // Unmarshal records the element name in that field.
  44. //
  45. // * If the XMLName field has an associated tag of the form
  46. // "name" or "namespace-URL name", the XML element must have
  47. // the given name (and, optionally, name space) or else Unmarshal
  48. // returns an error.
  49. //
  50. // * If the XML element has an attribute whose name matches a
  51. // struct field name with an associated tag containing ",attr" or
  52. // the explicit name in a struct field tag of the form "name,attr",
  53. // Unmarshal records the attribute value in that field.
  54. //
  55. // * If the XML element has an attribute not handled by the previous
  56. // rule and the struct has a field with an associated tag containing
  57. // ",any,attr", Unmarshal records the attribute value in the first
  58. // such field.
  59. //
  60. // * If the XML element contains character data, that data is
  61. // accumulated in the first struct field that has tag ",chardata".
  62. // The struct field may have type []byte or string.
  63. // If there is no such field, the character data is discarded.
  64. //
  65. // * If the XML element contains comments, they are accumulated in
  66. // the first struct field that has tag ",comment". The struct
  67. // field may have type []byte or string. If there is no such
  68. // field, the comments are discarded.
  69. //
  70. // * If the XML element contains a sub-element whose name matches
  71. // the prefix of a tag formatted as "a" or "a>b>c", unmarshal
  72. // will descend into the XML structure looking for elements with the
  73. // given names, and will map the innermost elements to that struct
  74. // field. A tag starting with ">" is equivalent to one starting
  75. // with the field name followed by ">".
  76. //
  77. // * If the XML element contains a sub-element whose name matches
  78. // a struct field's XMLName tag and the struct field has no
  79. // explicit name tag as per the previous rule, unmarshal maps
  80. // the sub-element to that struct field.
  81. //
  82. // * If the XML element contains a sub-element whose name matches a
  83. // field without any mode flags (",attr", ",chardata", etc), Unmarshal
  84. // maps the sub-element to that struct field.
  85. //
  86. // * If the XML element contains a sub-element that hasn't matched any
  87. // of the above rules and the struct has a field with tag ",any",
  88. // unmarshal maps the sub-element to that struct field.
  89. //
  90. // * An anonymous struct field is handled as if the fields of its
  91. // value were part of the outer struct.
  92. //
  93. // * A struct field with tag "-" is never unmarshaled into.
  94. //
  95. // Unmarshal maps an XML element to a string or []byte by saving the
  96. // concatenation of that element's character data in the string or
  97. // []byte. The saved []byte is never nil.
  98. //
  99. // Unmarshal maps an attribute value to a string or []byte by saving
  100. // the value in the string or slice.
  101. //
  102. // Unmarshal maps an attribute value to an Attr by saving the attribute,
  103. // including its name, in the Attr.
  104. //
  105. // Unmarshal maps an XML element or attribute value to a slice by
  106. // extending the length of the slice and mapping the element or attribute
  107. // to the newly created value.
  108. //
  109. // Unmarshal maps an XML element or attribute value to a bool by
  110. // setting it to the boolean value represented by the string. Whitespace
  111. // is trimmed and ignored.
  112. //
  113. // Unmarshal maps an XML element or attribute value to an integer or
  114. // floating-point field by setting the field to the result of
  115. // interpreting the string value in decimal. There is no check for
  116. // overflow. Whitespace is trimmed and ignored.
  117. //
  118. // Unmarshal maps an XML element to a Name by recording the element
  119. // name.
  120. //
  121. // Unmarshal maps an XML element to a pointer by setting the pointer
  122. // to a freshly allocated value and then mapping the element to that value.
  123. //
  124. // A missing element or empty attribute value will be unmarshaled as a zero value.
  125. // If the field is a slice, a zero value will be appended to the field. Otherwise, the
  126. // field will be set to its zero value.
  127. func Unmarshal(data []byte, v interface{}) error {
  128. return NewDecoder(bytes.NewReader(data)).Decode(v)
  129. }
  130.  
  131. // Decode works like Unmarshal, except it reads the decoder
  132. // stream to find the start element.
  133. func (d *Decoder) Decode(v interface{}) error {
  134. return d.DecodeElement(v, nil)
  135. }
  136.  
  137. // DecodeElement works like Unmarshal except that it takes
  138. // a pointer to the start XML element to decode into v.
  139. // It is useful when a client reads some raw XML tokens itself
  140. // but also wants to defer to Unmarshal for some elements.
  141. func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
  142. val := reflect.ValueOf(v)
  143. if val.Kind() != reflect.Ptr {
  144. return errors.New("non-pointer passed to Unmarshal")
  145. }
  146. return d.unmarshal(val.Elem(), start)
  147. }
  148.  
  149. // An UnmarshalError represents an error in the unmarshaling process.
  150. type UnmarshalError string
  151.  
  152. func (e UnmarshalError) Error() string { return string(e) }
  153.  
  154. // Unmarshaler is the interface implemented by objects that can unmarshal
  155. // an XML element description of themselves.
  156. //
  157. // UnmarshalXML decodes a single XML element
  158. // beginning with the given start element.
  159. // If it returns an error, the outer call to Unmarshal stops and
  160. // returns that error.
  161. // UnmarshalXML must consume exactly one XML element.
  162. // One common implementation strategy is to unmarshal into
  163. // a separate value with a layout matching the expected XML
  164. // using d.DecodeElement, and then to copy the data from
  165. // that value into the receiver.
  166. // Another common strategy is to use d.Token to process the
  167. // XML object one token at a time.
  168. // UnmarshalXML may not use d.RawToken.
  169. type Unmarshaler interface {
  170. UnmarshalXML(d *Decoder, start StartElement) error
  171. }
  172.  
  173. // UnmarshalerAttr is the interface implemented by objects that can unmarshal
  174. // an XML attribute description of themselves.
  175. //
  176. // UnmarshalXMLAttr decodes a single XML attribute.
  177. // If it returns an error, the outer call to Unmarshal stops and
  178. // returns that error.
  179. // UnmarshalXMLAttr is used only for struct fields with the
  180. // "attr" option in the field tag.
  181. type UnmarshalerAttr interface {
  182. UnmarshalXMLAttr(attr Attr) error
  183. }
  184.  
  185. // receiverType returns the receiver type to use in an expression like "%s.MethodName".
  186. func receiverType(val interface{}) string {
  187. t := reflect.TypeOf(val)
  188. if t.Name() != "" {
  189. return t.String()
  190. }
  191. return "(" + t.String() + ")"
  192. }
  193.  
  194. // unmarshalInterface unmarshals a single XML element into val.
  195. // start is the opening tag of the element.
  196. func (d *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error {
  197. // Record that decoder must stop at end tag corresponding to start.
  198. d.pushEOF()
  199.  
  200. d.unmarshalDepth++
  201. err := val.UnmarshalXML(d, *start)
  202. d.unmarshalDepth--
  203. if err != nil {
  204. d.popEOF()
  205. return err
  206. }
  207.  
  208. if !d.popEOF() {
  209. return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(val), start.Name.Local)
  210. }
  211.  
  212. return nil
  213. }
  214.  
  215. // unmarshalTextInterface unmarshals a single XML element into val.
  216. // The chardata contained in the element (but not its children)
  217. // is passed to the text unmarshaler.
  218. func (d *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler) error {
  219. var buf []byte
  220. depth := 1
  221. for depth > 0 {
  222. t, err := d.Token()
  223. if err != nil {
  224. return err
  225. }
  226. switch t := t.(type) {
  227. case CharData:
  228. if depth == 1 {
  229. buf = append(buf, t...)
  230. }
  231. case StartElement:
  232. depth++
  233. case EndElement:
  234. depth--
  235. }
  236. }
  237. return val.UnmarshalText(buf)
  238. }
  239.  
  240. // unmarshalAttr unmarshals a single XML attribute into val.
  241. func (d *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
  242. if val.Kind() == reflect.Ptr {
  243. if val.IsNil() {
  244. val.Set(reflect.New(val.Type().Elem()))
  245. }
  246. val = val.Elem()
  247. }
  248. if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
  249. // This is an unmarshaler with a non-pointer receiver,
  250. // so it's likely to be incorrect, but we do what we're told.
  251. return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
  252. }
  253. if val.CanAddr() {
  254. pv := val.Addr()
  255. if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) {
  256. return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
  257. }
  258. }
  259.  
  260. // Not an UnmarshalerAttr; try encoding.TextUnmarshaler.
  261. if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
  262. // This is an unmarshaler with a non-pointer receiver,
  263. // so it's likely to be incorrect, but we do what we're told.
  264. return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
  265. }
  266. if val.CanAddr() {
  267. pv := val.Addr()
  268. if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
  269. return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
  270. }
  271. }
  272.  
  273. if val.Type().Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
  274. // Slice of element values.
  275. // Grow slice.
  276. n := val.Len()
  277. val.Set(reflect.Append(val, reflect.Zero(val.Type().Elem())))
  278.  
  279. // Recur to read element into slice.
  280. if err := d.unmarshalAttr(val.Index(n), attr); err != nil {
  281. val.SetLen(n)
  282. return err
  283. }
  284. return nil
  285. }
  286.  
  287. if val.Type() == attrType {
  288. val.Set(reflect.ValueOf(attr))
  289. return nil
  290. }
  291.  
  292. return copyValue(val, nil, attr.Value)
  293. }
  294.  
  295. var (
  296. attrType = reflect.TypeOf(Attr{})
  297. unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
  298. unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
  299. textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
  300. )
  301.  
  302. // Unmarshal a single XML element into val.
  303. func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
  304. // Find start element if we need it.
  305. if start == nil {
  306. for {
  307. tok, err := d.Token()
  308. if err != nil {
  309. return err
  310. }
  311. if t, ok := tok.(StartElement); ok {
  312. start = &t
  313. break
  314. }
  315. }
  316. }
  317.  
  318. // Load value from interface, but only if the result will be
  319. // usefully addressable.
  320. if val.Kind() == reflect.Interface && !val.IsNil() {
  321. e := val.Elem()
  322. if e.Kind() == reflect.Ptr && !e.IsNil() {
  323. val = e
  324. }
  325. }
  326.  
  327. if val.Kind() == reflect.Ptr {
  328. if val.IsNil() {
  329. val.Set(reflect.New(val.Type().Elem()))
  330. }
  331. val = val.Elem()
  332. }
  333.  
  334. if val.CanInterface() && val.Type().Implements(unmarshalerType) {
  335. // This is an unmarshaler with a non-pointer receiver,
  336. // so it's likely to be incorrect, but we do what we're told.
  337. return d.unmarshalInterface(val.Interface().(Unmarshaler), start)
  338. }
  339.  
  340. if val.CanAddr() {
  341. pv := val.Addr()
  342. if pv.CanInterface() && pv.Type().Implements(unmarshalerType) {
  343. return d.unmarshalInterface(pv.Interface().(Unmarshaler), start)
  344. }
  345. }
  346.  
  347. if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
  348. return d.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler))
  349. }
  350.  
  351. if val.CanAddr() {
  352. pv := val.Addr()
  353. if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
  354. return d.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler))
  355. }
  356. }
  357.  
  358. var (
  359. data []byte
  360. saveData reflect.Value
  361. comment []byte
  362. saveComment reflect.Value
  363. saveXML reflect.Value
  364. saveXMLIndex int
  365. saveXMLData []byte
  366. saveAny reflect.Value
  367. sv reflect.Value
  368. tinfo *typeInfo
  369. err error
  370. )
  371.  
  372. switch v := val; v.Kind() {
  373. default:
  374. return errors.New("unknown type " + v.Type().String())
  375.  
  376. case reflect.Interface:
  377. // TODO: For now, simply ignore the field. In the near
  378. // future we may choose to unmarshal the start
  379. // element on it, if not nil.
  380. return d.Skip()
  381.  
  382. case reflect.Slice:
  383. typ := v.Type()
  384. if typ.Elem().Kind() == reflect.Uint8 {
  385. // []byte
  386. saveData = v
  387. break
  388. }
  389.  
  390. // Slice of element values.
  391. // Grow slice.
  392. n := v.Len()
  393. v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
  394.  
  395. // Recur to read element into slice.
  396. if err := d.unmarshal(v.Index(n), start); err != nil {
  397. v.SetLen(n)
  398. return err
  399. }
  400. return nil
  401.  
  402. case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
  403. saveData = v
  404.  
  405. case reflect.Struct:
  406. typ := v.Type()
  407. if typ == nameType {
  408. v.Set(reflect.ValueOf(start.Name))
  409. break
  410. }
  411.  
  412. sv = v
  413. tinfo, err = getTypeInfo(typ)
  414. if err != nil {
  415. return err
  416. }
  417.  
  418. // Validate and assign element name.
  419. if tinfo.xmlname != nil {
  420. finfo := tinfo.xmlname
  421. if finfo.name != "" && finfo.name != start.Name.Local {
  422. return UnmarshalError("expected element type <" + finfo.name + "> but have <" + start.Name.Local + ">")
  423. }
  424. if finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
  425. e := "expected element <" + finfo.name + "> in name space " + finfo.xmlns + " but have "
  426. if start.Name.Space == "" {
  427. e += "no name space"
  428. } else {
  429. e += start.Name.Space
  430. }
  431. return UnmarshalError(e)
  432. }
  433. fv := finfo.value(sv)
  434. if _, ok := fv.Interface().(Name); ok {
  435. fv.Set(reflect.ValueOf(start.Name))
  436. }
  437. }
  438.  
  439. // Assign attributes.
  440. for _, a := range start.Attr {
  441. handled := false
  442. any := -1
  443. for i := range tinfo.fields {
  444. finfo := &tinfo.fields[i]
  445. switch finfo.flags & fMode {
  446. case fAttr:
  447. strv := finfo.value(sv)
  448. if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
  449. if err := d.unmarshalAttr(strv, a); err != nil {
  450. return err
  451. }
  452. handled = true
  453. }
  454.  
  455. case fAny | fAttr:
  456. if any == -1 {
  457. any = i
  458. }
  459. }
  460. }
  461. if !handled && any >= 0 {
  462. finfo := &tinfo.fields[any]
  463. strv := finfo.value(sv)
  464. if err := d.unmarshalAttr(strv, a); err != nil {
  465. return err
  466. }
  467. }
  468. }
  469.  
  470. // Determine whether we need to save character data or comments.
  471. for i := range tinfo.fields {
  472. finfo := &tinfo.fields[i]
  473. switch finfo.flags & fMode {
  474. case fCDATA, fCharData:
  475. if !saveData.IsValid() {
  476. saveData = finfo.value(sv)
  477. }
  478.  
  479. case fComment:
  480. if !saveComment.IsValid() {
  481. saveComment = finfo.value(sv)
  482. }
  483.  
  484. case fAny, fAny | fElement:
  485. if !saveAny.IsValid() {
  486. saveAny = finfo.value(sv)
  487. }
  488.  
  489. case fInnerXml:
  490. if !saveXML.IsValid() {
  491. saveXML = finfo.value(sv)
  492. if d.saved == nil {
  493. saveXMLIndex = 0
  494. d.saved = new(bytes.Buffer)
  495. } else {
  496. saveXMLIndex = d.savedOffset()
  497. }
  498. }
  499. }
  500. }
  501. }
  502.  
  503. // Find end element.
  504. // Process sub-elements along the way.
  505. Loop:
  506. for {
  507. var savedOffset int
  508. if saveXML.IsValid() {
  509. savedOffset = d.savedOffset()
  510. }
  511. tok, err := d.Token()
  512. if err != nil {
  513. return err
  514. }
  515. switch t := tok.(type) {
  516. case StartElement:
  517. consumed := false
  518. if sv.IsValid() {
  519. consumed, err = d.unmarshalPath(tinfo, sv, nil, &t)
  520. if err != nil {
  521. return err
  522. }
  523. if !consumed && saveAny.IsValid() {
  524. consumed = true
  525. if err := d.unmarshal(saveAny, &t); err != nil {
  526. return err
  527. }
  528. }
  529. }
  530. if !consumed {
  531. if err := d.Skip(); err != nil {
  532. return err
  533. }
  534. }
  535.  
  536. case EndElement:
  537. if saveXML.IsValid() {
  538. saveXMLData = d.saved.Bytes()[saveXMLIndex:savedOffset]
  539. if saveXMLIndex == 0 {
  540. d.saved = nil
  541. }
  542. }
  543. break Loop
  544.  
  545. case CharData:
  546. if saveData.IsValid() {
  547. data = append(data, t...)
  548. }
  549.  
  550. case Comment:
  551. if saveComment.IsValid() {
  552. comment = append(comment, t...)
  553. }
  554. }
  555. }
  556.  
  557. if saveData.IsValid() && saveData.CanInterface() && saveData.Type().Implements(textUnmarshalerType) {
  558. if err := saveData.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
  559. return err
  560. }
  561. saveData = reflect.Value{}
  562. }
  563.  
  564. if saveData.IsValid() && saveData.CanAddr() {
  565. pv := saveData.Addr()
  566. if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
  567. if err := pv.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
  568. return err
  569. }
  570. saveData = reflect.Value{}
  571. }
  572. }
  573.  
  574. if err := copyValue(saveData, data, ""); err != nil {
  575. return err
  576. }
  577.  
  578. switch t := saveComment; t.Kind() {
  579. case reflect.String:
  580. t.SetString(string(comment))
  581. case reflect.Slice:
  582. t.Set(reflect.ValueOf(comment))
  583. }
  584.  
  585. switch t := saveXML; t.Kind() {
  586. case reflect.String:
  587. t.SetString(string(saveXMLData))
  588. case reflect.Slice:
  589. if t.Type().Elem().Kind() == reflect.Uint8 {
  590. t.Set(reflect.ValueOf(saveXMLData))
  591. }
  592. }
  593.  
  594. return nil
  595. }
  596.  
  597. func copyValue(dst reflect.Value, src []byte, srcstr string) (err error) {
  598. dst0 := dst
  599.  
  600. if dst.Kind() == reflect.Ptr {
  601. if dst.IsNil() {
  602. dst.Set(reflect.New(dst.Type().Elem()))
  603. }
  604. dst = dst.Elem()
  605. }
  606.  
  607. if len(src) != 0 && len(srcstr) != 0 {
  608. panic("two sources given to copyValue")
  609. }
  610.  
  611. // Save accumulated data.
  612. switch dst.Kind() {
  613. case reflect.Invalid:
  614. // Probably a comment.
  615. default:
  616. return errors.New("cannot unmarshal into " + dst0.Type().String())
  617. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  618. if src != nil {
  619. srcstr = string(src)
  620. }
  621. if len(srcstr) == 0 {
  622. dst.SetInt(0)
  623. return nil
  624. }
  625. itmp, err := strconv.ParseInt(strings.TrimSpace(srcstr), 10, dst.Type().Bits())
  626. if err != nil {
  627. return err
  628. }
  629. dst.SetInt(itmp)
  630. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  631. if len(src) != 0 {
  632. srcstr = string(src)
  633. }
  634. if len(srcstr) == 0 {
  635. dst.SetUint(0)
  636. return nil
  637. }
  638. utmp, err := strconv.ParseUint(strings.TrimSpace(srcstr), 10, dst.Type().Bits())
  639. if err != nil {
  640. return err
  641. }
  642. dst.SetUint(utmp)
  643. case reflect.Float32, reflect.Float64:
  644. if len(src) != 0 {
  645. srcstr = string(src)
  646. }
  647. if len(srcstr) == 0 {
  648. dst.SetFloat(0)
  649. return nil
  650. }
  651. ftmp, err := strconv.ParseFloat(strings.TrimSpace(srcstr), dst.Type().Bits())
  652. if err != nil {
  653. return err
  654. }
  655. dst.SetFloat(ftmp)
  656. case reflect.Bool:
  657. if len(src) != 0 {
  658. srcstr = string(src)
  659. }
  660. if len(srcstr) == 0 {
  661. dst.SetBool(false)
  662. return nil
  663. }
  664. value, err := strconv.ParseBool(strings.TrimSpace(srcstr))
  665. if err != nil {
  666. return err
  667. }
  668. dst.SetBool(value)
  669. case reflect.String:
  670. if len(src) != 0 {
  671. srcstr = string(src)
  672. }
  673. dst.SetString(srcstr)
  674. case reflect.Slice:
  675. if len(srcstr) != 0 {
  676. src = []byte(srcstr)
  677. }
  678. if len(src) == 0 {
  679. // non-nil to flag presence
  680. src = []byte{}
  681. }
  682. dst.SetBytes(src)
  683. }
  684. return nil
  685. }
  686.  
  687. // unmarshalPath walks down an XML structure looking for wanted
  688. // paths, and calls unmarshal on them.
  689. // The consumed result tells whether XML elements have been consumed
  690. // from the Decoder until start's matching end element, or if it's
  691. // still untouched because start is uninteresting for sv's fields.
  692. func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
  693. recurse := false
  694. Loop:
  695. for i := range tinfo.fields {
  696. finfo := &tinfo.fields[i]
  697. if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) || finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
  698. continue
  699. }
  700. for j := range parents {
  701. if parents[j] != finfo.parents[j] {
  702. continue Loop
  703. }
  704. }
  705. if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
  706. // It's a perfect match, unmarshal the field.
  707. return true, d.unmarshal(finfo.value(sv), start)
  708. }
  709. if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
  710. // It's a prefix for the field. Break and recurse
  711. // since it's not ok for one field path to be itself
  712. // the prefix for another field path.
  713. recurse = true
  714.  
  715. // We can reuse the same slice as long as we
  716. // don't try to append to it.
  717. parents = finfo.parents[:len(parents)+1]
  718. break
  719. }
  720. }
  721. if !recurse {
  722. // We have no business with this element.
  723. return false, nil
  724. }
  725. // The element is not a perfect match for any field, but one
  726. // or more fields have the path to this element as a parent
  727. // prefix. Recurse and attempt to match these.
  728. for {
  729. var tok Token
  730. tok, err = d.Token()
  731. if err != nil {
  732. return true, err
  733. }
  734. switch t := tok.(type) {
  735. case StartElement:
  736. consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t)
  737. if err != nil {
  738. return true, err
  739. }
  740. if !consumed2 {
  741. if err := d.Skip(); err != nil {
  742. return true, err
  743. }
  744. }
  745. case EndElement:
  746. return true, nil
  747. }
  748. }
  749. }
  750.  
  751. // Skip reads tokens until it has consumed the end element
  752. // matching the most recent start element already consumed.
  753. // It recurs if it encounters a start element, so it can be used to
  754. // skip nested structures.
  755. // It returns nil if it finds an end element matching the start
  756. // element; otherwise it returns an error describing the problem.
  757. func (d *Decoder) Skip() error {
  758. for {
  759. tok, err := d.Token()
  760. if err != nil {
  761. return err
  762. }
  763. switch tok.(type) {
  764. case StartElement:
  765. if err := d.Skip(); err != nil {
  766. return err
  767. }
  768. case EndElement:
  769. return nil
  770. }
  771. }
  772. }
Add Comment
Please, Sign In to add comment