keyvalues.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. // Copyright 2012-2014 Charles Banning. 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. // keyvalues.go: Extract values from an arbitrary XML doc. Tag path can include wildcard characters.
  5. package mxj
  6. import (
  7. "errors"
  8. "fmt"
  9. "strconv"
  10. "strings"
  11. )
  12. // ----------------------------- get everything FOR a single key -------------------------
  13. const (
  14. minArraySize = 32
  15. )
  16. var defaultArraySize int = minArraySize
  17. // SetArraySize adjust the buffers for expected number of values to return from ValuesForKey() and ValuesForPath().
  18. // This can have the effect of significantly reducing memory allocation-copy functions for large data sets.
  19. // Returns the initial buffer size.
  20. func SetArraySize(size int) int {
  21. if size > minArraySize {
  22. defaultArraySize = size
  23. } else {
  24. defaultArraySize = minArraySize
  25. }
  26. return defaultArraySize
  27. }
  28. // ValuesForKey return all values in Map, 'mv', associated with a 'key'. If len(returned_values) == 0, then no match.
  29. // On error, the returned slice is 'nil'. NOTE: 'key' can be wildcard, "*".
  30. // 'subkeys' (optional) are "key:val[:type]" strings representing attributes or elements in a list.
  31. // - By default 'val' is of type string. "key:val:bool" and "key:val:float" to coerce them.
  32. // - For attributes prefix the label with the attribute prefix character, by default a
  33. // hyphen, '-', e.g., "-seq:3". (See SetAttrPrefix function.)
  34. // - If the 'key' refers to a list, then "key:value" could select a list member of the list.
  35. // - The subkey can be wildcarded - "key:*" - to require that it's there with some value.
  36. // - If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an
  37. // exclusion critera - e.g., "!author:William T. Gaddis".
  38. // - If val contains ":" symbol, use SetFieldSeparator to a unused symbol, perhaps "|".
  39. func (mv Map) ValuesForKey(key string, subkeys ...string) ([]interface{}, error) {
  40. m := map[string]interface{}(mv)
  41. var subKeyMap map[string]interface{}
  42. if len(subkeys) > 0 {
  43. var err error
  44. subKeyMap, err = getSubKeyMap(subkeys...)
  45. if err != nil {
  46. return nil, err
  47. }
  48. }
  49. ret := make([]interface{}, 0, defaultArraySize)
  50. var cnt int
  51. hasKey(m, key, &ret, &cnt, subKeyMap)
  52. return ret[:cnt], nil
  53. }
  54. var KeyNotExistError = errors.New("Key does not exist")
  55. // ValueForKey is a wrapper on ValuesForKey. It returns the first member of []interface{}, if any.
  56. // If there is no value, "nil, nil" is returned.
  57. func (mv Map) ValueForKey(key string, subkeys ...string) (interface{}, error) {
  58. vals, err := mv.ValuesForKey(key, subkeys...)
  59. if err != nil {
  60. return nil, err
  61. }
  62. if len(vals) == 0 {
  63. return nil, KeyNotExistError
  64. }
  65. return vals[0], nil
  66. }
  67. // hasKey - if the map 'key' exists append it to array
  68. // if it doesn't do nothing except scan array and map values
  69. func hasKey(iv interface{}, key string, ret *[]interface{}, cnt *int, subkeys map[string]interface{}) {
  70. // func hasKey(iv interface{}, key string, ret *[]interface{}, subkeys map[string]interface{}) {
  71. switch iv.(type) {
  72. case map[string]interface{}:
  73. vv := iv.(map[string]interface{})
  74. // see if the current value is of interest
  75. if v, ok := vv[key]; ok {
  76. switch v.(type) {
  77. case map[string]interface{}:
  78. if hasSubKeys(v, subkeys) {
  79. *ret = append(*ret, v)
  80. *cnt++
  81. }
  82. case []interface{}:
  83. for _, av := range v.([]interface{}) {
  84. if hasSubKeys(av, subkeys) {
  85. *ret = append(*ret, av)
  86. *cnt++
  87. }
  88. }
  89. default:
  90. if len(subkeys) == 0 {
  91. *ret = append(*ret, v)
  92. *cnt++
  93. }
  94. }
  95. }
  96. // wildcard case
  97. if key == "*" {
  98. for _, v := range vv {
  99. switch v.(type) {
  100. case map[string]interface{}:
  101. if hasSubKeys(v, subkeys) {
  102. *ret = append(*ret, v)
  103. *cnt++
  104. }
  105. case []interface{}:
  106. for _, av := range v.([]interface{}) {
  107. if hasSubKeys(av, subkeys) {
  108. *ret = append(*ret, av)
  109. *cnt++
  110. }
  111. }
  112. default:
  113. if len(subkeys) == 0 {
  114. *ret = append(*ret, v)
  115. *cnt++
  116. }
  117. }
  118. }
  119. }
  120. // scan the rest
  121. for _, v := range vv {
  122. hasKey(v, key, ret, cnt, subkeys)
  123. }
  124. case []interface{}:
  125. for _, v := range iv.([]interface{}) {
  126. hasKey(v, key, ret, cnt, subkeys)
  127. }
  128. }
  129. }
  130. // ----------------------- get everything for a node in the Map ---------------------------
  131. // Allow indexed arrays in "path" specification. (Request from Abhijit Kadam - abhijitk100@gmail.com.)
  132. // 2014.04.28 - implementation note.
  133. // Implemented as a wrapper of (old)ValuesForPath() because we need look-ahead logic to handle expansion
  134. // of wildcards and unindexed arrays. Embedding such logic into valuesForKeyPath() would have made the
  135. // code much more complicated; this wrapper is straightforward, easy to debug, and doesn't add significant overhead.
  136. // ValuesForPatb retrieves all values for a path from the Map. If len(returned_values) == 0, then no match.
  137. // On error, the returned array is 'nil'.
  138. // 'path' is a dot-separated path of key values.
  139. // - If a node in the path is '*', then everything beyond is walked.
  140. // - 'path' can contain indexed array references, such as, "*.data[1]" and "msgs[2].data[0].field" -
  141. // even "*[2].*[0].field".
  142. // 'subkeys' (optional) are "key:val[:type]" strings representing attributes or elements in a list.
  143. // - By default 'val' is of type string. "key:val:bool" and "key:val:float" to coerce them.
  144. // - For attributes prefix the label with the attribute prefix character, by default a
  145. // hyphen, '-', e.g., "-seq:3". (See SetAttrPrefix function.)
  146. // - If the 'path' refers to a list, then "tag:value" would return member of the list.
  147. // - The subkey can be wildcarded - "key:*" - to require that it's there with some value.
  148. // - If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an
  149. // exclusion critera - e.g., "!author:William T. Gaddis".
  150. // - If val contains ":" symbol, use SetFieldSeparator to a unused symbol, perhaps "|".
  151. func (mv Map) ValuesForPath(path string, subkeys ...string) ([]interface{}, error) {
  152. // If there are no array indexes in path, use legacy ValuesForPath() logic.
  153. if strings.Index(path, "[") < 0 {
  154. return mv.oldValuesForPath(path, subkeys...)
  155. }
  156. var subKeyMap map[string]interface{}
  157. if len(subkeys) > 0 {
  158. var err error
  159. subKeyMap, err = getSubKeyMap(subkeys...)
  160. if err != nil {
  161. return nil, err
  162. }
  163. }
  164. keys, kerr := parsePath(path)
  165. if kerr != nil {
  166. return nil, kerr
  167. }
  168. vals, verr := valuesForArray(keys, mv)
  169. if verr != nil {
  170. return nil, verr // Vals may be nil, but return empty array.
  171. }
  172. // Need to handle subkeys ... only return members of vals that satisfy conditions.
  173. retvals := make([]interface{}, 0)
  174. for _, v := range vals {
  175. if hasSubKeys(v, subKeyMap) {
  176. retvals = append(retvals, v)
  177. }
  178. }
  179. return retvals, nil
  180. }
  181. func valuesForArray(keys []*key, m Map) ([]interface{}, error) {
  182. var tmppath string
  183. var haveFirst bool
  184. var vals []interface{}
  185. var verr error
  186. lastkey := len(keys) - 1
  187. for i := 0; i <= lastkey; i++ {
  188. if !haveFirst {
  189. tmppath = keys[i].name
  190. haveFirst = true
  191. } else {
  192. tmppath += "." + keys[i].name
  193. }
  194. // Look-ahead: explode wildcards and unindexed arrays.
  195. // Need to handle un-indexed list recursively:
  196. // e.g., path is "stuff.data[0]" rather than "stuff[0].data[0]".
  197. // Need to treat it as "stuff[0].data[0]", "stuff[1].data[0]", ...
  198. if !keys[i].isArray && i < lastkey && keys[i+1].isArray {
  199. // Can't pass subkeys because we may not be at literal end of path.
  200. vv, vverr := m.oldValuesForPath(tmppath)
  201. if vverr != nil {
  202. return nil, vverr
  203. }
  204. for _, v := range vv {
  205. // See if we can walk the value.
  206. am, ok := v.(map[string]interface{})
  207. if !ok {
  208. continue
  209. }
  210. // Work the backend.
  211. nvals, nvalserr := valuesForArray(keys[i+1:], Map(am))
  212. if nvalserr != nil {
  213. return nil, nvalserr
  214. }
  215. vals = append(vals, nvals...)
  216. }
  217. break // have recursed the whole path - return
  218. }
  219. if keys[i].isArray || i == lastkey {
  220. // Don't pass subkeys because may not be at literal end of path.
  221. vals, verr = m.oldValuesForPath(tmppath)
  222. } else {
  223. continue
  224. }
  225. if verr != nil {
  226. return nil, verr
  227. }
  228. if i == lastkey && !keys[i].isArray {
  229. break
  230. }
  231. // Now we're looking at an array - supposedly.
  232. // Is index in range of vals?
  233. if len(vals) <= keys[i].position {
  234. vals = nil
  235. break
  236. }
  237. // Return the array member of interest, if at end of path.
  238. if i == lastkey {
  239. vals = vals[keys[i].position:(keys[i].position + 1)]
  240. break
  241. }
  242. // Extract the array member of interest.
  243. am := vals[keys[i].position:(keys[i].position + 1)]
  244. // must be a map[string]interface{} value so we can keep walking the path
  245. amm, ok := am[0].(map[string]interface{})
  246. if !ok {
  247. vals = nil
  248. break
  249. }
  250. m = Map(amm)
  251. haveFirst = false
  252. }
  253. return vals, nil
  254. }
  255. type key struct {
  256. name string
  257. isArray bool
  258. position int
  259. }
  260. func parsePath(s string) ([]*key, error) {
  261. keys := strings.Split(s, ".")
  262. ret := make([]*key, 0)
  263. for i := 0; i < len(keys); i++ {
  264. if keys[i] == "" {
  265. continue
  266. }
  267. newkey := new(key)
  268. if strings.Index(keys[i], "[") < 0 {
  269. newkey.name = keys[i]
  270. ret = append(ret, newkey)
  271. continue
  272. }
  273. p := strings.Split(keys[i], "[")
  274. newkey.name = p[0]
  275. p = strings.Split(p[1], "]")
  276. if p[0] == "" { // no right bracket
  277. return nil, fmt.Errorf("no right bracket on key index: %s", keys[i])
  278. }
  279. // convert p[0] to a int value
  280. pos, nerr := strconv.ParseInt(p[0], 10, 32)
  281. if nerr != nil {
  282. return nil, fmt.Errorf("cannot convert index to int value: %s", p[0])
  283. }
  284. newkey.position = int(pos)
  285. newkey.isArray = true
  286. ret = append(ret, newkey)
  287. }
  288. return ret, nil
  289. }
  290. // legacy ValuesForPath() - now wrapped to handle special case of indexed arrays in 'path'.
  291. func (mv Map) oldValuesForPath(path string, subkeys ...string) ([]interface{}, error) {
  292. m := map[string]interface{}(mv)
  293. var subKeyMap map[string]interface{}
  294. if len(subkeys) > 0 {
  295. var err error
  296. subKeyMap, err = getSubKeyMap(subkeys...)
  297. if err != nil {
  298. return nil, err
  299. }
  300. }
  301. keys := strings.Split(path, ".")
  302. if keys[len(keys)-1] == "" {
  303. keys = keys[:len(keys)-1]
  304. }
  305. ivals := make([]interface{}, 0, defaultArraySize)
  306. var cnt int
  307. valuesForKeyPath(&ivals, &cnt, m, keys, subKeyMap)
  308. return ivals[:cnt], nil
  309. }
  310. func valuesForKeyPath(ret *[]interface{}, cnt *int, m interface{}, keys []string, subkeys map[string]interface{}) {
  311. lenKeys := len(keys)
  312. // load 'm' values into 'ret'
  313. // expand any lists
  314. if lenKeys == 0 {
  315. switch m.(type) {
  316. case map[string]interface{}:
  317. if subkeys != nil {
  318. if ok := hasSubKeys(m, subkeys); !ok {
  319. return
  320. }
  321. }
  322. *ret = append(*ret, m)
  323. *cnt++
  324. case []interface{}:
  325. for i, v := range m.([]interface{}) {
  326. if subkeys != nil {
  327. if ok := hasSubKeys(v, subkeys); !ok {
  328. continue // only load list members with subkeys
  329. }
  330. }
  331. *ret = append(*ret, (m.([]interface{}))[i])
  332. *cnt++
  333. }
  334. default:
  335. if subkeys != nil {
  336. return // must be map[string]interface{} if there are subkeys
  337. }
  338. *ret = append(*ret, m)
  339. *cnt++
  340. }
  341. return
  342. }
  343. // key of interest
  344. key := keys[0]
  345. switch key {
  346. case "*": // wildcard - scan all values
  347. switch m.(type) {
  348. case map[string]interface{}:
  349. for _, v := range m.(map[string]interface{}) {
  350. // valuesForKeyPath(ret, v, keys[1:], subkeys)
  351. valuesForKeyPath(ret, cnt, v, keys[1:], subkeys)
  352. }
  353. case []interface{}:
  354. for _, v := range m.([]interface{}) {
  355. switch v.(type) {
  356. // flatten out a list of maps - keys are processed
  357. case map[string]interface{}:
  358. for _, vv := range v.(map[string]interface{}) {
  359. // valuesForKeyPath(ret, vv, keys[1:], subkeys)
  360. valuesForKeyPath(ret, cnt, vv, keys[1:], subkeys)
  361. }
  362. default:
  363. // valuesForKeyPath(ret, v, keys[1:], subkeys)
  364. valuesForKeyPath(ret, cnt, v, keys[1:], subkeys)
  365. }
  366. }
  367. }
  368. default: // key - must be map[string]interface{}
  369. switch m.(type) {
  370. case map[string]interface{}:
  371. if v, ok := m.(map[string]interface{})[key]; ok {
  372. // valuesForKeyPath(ret, v, keys[1:], subkeys)
  373. valuesForKeyPath(ret, cnt, v, keys[1:], subkeys)
  374. }
  375. case []interface{}: // may be buried in list
  376. for _, v := range m.([]interface{}) {
  377. switch v.(type) {
  378. case map[string]interface{}:
  379. if vv, ok := v.(map[string]interface{})[key]; ok {
  380. // valuesForKeyPath(ret, vv, keys[1:], subkeys)
  381. valuesForKeyPath(ret, cnt, vv, keys[1:], subkeys)
  382. }
  383. }
  384. }
  385. }
  386. }
  387. }
  388. // hasSubKeys() - interface{} equality works for string, float64, bool
  389. // 'v' must be a map[string]interface{} value to have subkeys
  390. // 'a' can have k:v pairs with v.(string) == "*", which is treated like a wildcard.
  391. func hasSubKeys(v interface{}, subkeys map[string]interface{}) bool {
  392. if len(subkeys) == 0 {
  393. return true
  394. }
  395. switch v.(type) {
  396. case map[string]interface{}:
  397. // do all subKey name:value pairs match?
  398. mv := v.(map[string]interface{})
  399. for skey, sval := range subkeys {
  400. isNotKey := false
  401. if skey[:1] == "!" { // a NOT-key
  402. skey = skey[1:]
  403. isNotKey = true
  404. }
  405. vv, ok := mv[skey]
  406. if !ok { // key doesn't exist
  407. if isNotKey { // key not there, but that's what we want
  408. if kv, ok := sval.(string); ok && kv == "*" {
  409. continue
  410. }
  411. }
  412. return false
  413. }
  414. // wildcard check
  415. if kv, ok := sval.(string); ok && kv == "*" {
  416. if isNotKey { // key is there, and we don't want it
  417. return false
  418. }
  419. continue
  420. }
  421. switch sval.(type) {
  422. case string:
  423. if s, ok := vv.(string); ok && s == sval.(string) {
  424. if isNotKey {
  425. return false
  426. }
  427. continue
  428. }
  429. case bool:
  430. if b, ok := vv.(bool); ok && b == sval.(bool) {
  431. if isNotKey {
  432. return false
  433. }
  434. continue
  435. }
  436. case float64:
  437. if f, ok := vv.(float64); ok && f == sval.(float64) {
  438. if isNotKey {
  439. return false
  440. }
  441. continue
  442. }
  443. }
  444. // key there but didn't match subkey value
  445. if isNotKey { // that's what we want
  446. continue
  447. }
  448. return false
  449. }
  450. // all subkeys matched
  451. return true
  452. }
  453. // not a map[string]interface{} value, can't have subkeys
  454. return false
  455. }
  456. // Generate map of key:value entries as map[string]string.
  457. // 'kv' arguments are "name:value" pairs: attribute keys are designated with prepended hyphen, '-'.
  458. // If len(kv) == 0, the return is (nil, nil).
  459. func getSubKeyMap(kv ...string) (map[string]interface{}, error) {
  460. if len(kv) == 0 {
  461. return nil, nil
  462. }
  463. m := make(map[string]interface{}, 0)
  464. for _, v := range kv {
  465. vv := strings.Split(v, fieldSep)
  466. switch len(vv) {
  467. case 2:
  468. m[vv[0]] = interface{}(vv[1])
  469. case 3:
  470. switch vv[2] {
  471. case "string", "char", "text":
  472. m[vv[0]] = interface{}(vv[1])
  473. case "bool", "boolean":
  474. // ParseBool treats "1"==true & "0"==false
  475. b, err := strconv.ParseBool(vv[1])
  476. if err != nil {
  477. return nil, fmt.Errorf("can't convert subkey value to bool: %s", vv[1])
  478. }
  479. m[vv[0]] = interface{}(b)
  480. case "float", "float64", "num", "number", "numeric":
  481. f, err := strconv.ParseFloat(vv[1], 64)
  482. if err != nil {
  483. return nil, fmt.Errorf("can't convert subkey value to float: %s", vv[1])
  484. }
  485. m[vv[0]] = interface{}(f)
  486. default:
  487. return nil, fmt.Errorf("unknown subkey conversion spec: %s", v)
  488. }
  489. default:
  490. return nil, fmt.Errorf("unknown subkey spec: %s", v)
  491. }
  492. }
  493. return m, nil
  494. }
  495. // ------------------------------- END of valuesFor ... ----------------------------
  496. // ----------------------- locate where a key value is in the tree -------------------
  497. //----------------------------- find all paths to a key --------------------------------
  498. // PathsForKey returns all paths through Map, 'mv', (in dot-notation) that terminate with the specified key.
  499. // Results can be used with ValuesForPath.
  500. func (mv Map) PathsForKey(key string) []string {
  501. m := map[string]interface{}(mv)
  502. breadbasket := make(map[string]bool, 0)
  503. breadcrumbs := ""
  504. hasKeyPath(breadcrumbs, m, key, breadbasket)
  505. if len(breadbasket) == 0 {
  506. return nil
  507. }
  508. // unpack map keys to return
  509. res := make([]string, len(breadbasket))
  510. var i int
  511. for k := range breadbasket {
  512. res[i] = k
  513. i++
  514. }
  515. return res
  516. }
  517. // PathForKeyShortest extracts the shortest path from all possible paths - from PathsForKey() - in Map, 'mv'..
  518. // Paths are strings using dot-notation.
  519. func (mv Map) PathForKeyShortest(key string) string {
  520. paths := mv.PathsForKey(key)
  521. lp := len(paths)
  522. if lp == 0 {
  523. return ""
  524. }
  525. if lp == 1 {
  526. return paths[0]
  527. }
  528. shortest := paths[0]
  529. shortestLen := len(strings.Split(shortest, "."))
  530. for i := 1; i < len(paths); i++ {
  531. vlen := len(strings.Split(paths[i], "."))
  532. if vlen < shortestLen {
  533. shortest = paths[i]
  534. shortestLen = vlen
  535. }
  536. }
  537. return shortest
  538. }
  539. // hasKeyPath - if the map 'key' exists append it to KeyPath.path and increment KeyPath.depth
  540. // This is really just a breadcrumber that saves all trails that hit the prescribed 'key'.
  541. func hasKeyPath(crumbs string, iv interface{}, key string, basket map[string]bool) {
  542. switch iv.(type) {
  543. case map[string]interface{}:
  544. vv := iv.(map[string]interface{})
  545. if _, ok := vv[key]; ok {
  546. // create a new breadcrumb, intialized with the one we have
  547. var nbc string
  548. if crumbs == "" {
  549. nbc = key
  550. } else {
  551. nbc = crumbs + "." + key
  552. }
  553. basket[nbc] = true
  554. }
  555. // walk on down the path, key could occur again at deeper node
  556. for k, v := range vv {
  557. // create a new breadcrumb, intialized with the one we have
  558. var nbc string
  559. if crumbs == "" {
  560. nbc = k
  561. } else {
  562. nbc = crumbs + "." + k
  563. }
  564. hasKeyPath(nbc, v, key, basket)
  565. }
  566. case []interface{}:
  567. // crumb-trail doesn't change, pass it on
  568. for _, v := range iv.([]interface{}) {
  569. hasKeyPath(crumbs, v, key, basket)
  570. }
  571. }
  572. }
  573. var PathNotExistError = errors.New("Path does not exist")
  574. // ValueForPath wraps ValuesFor Path and returns the first value returned.
  575. // If no value is found it returns 'nil' and PathNotExistError.
  576. func (mv Map) ValueForPath(path string) (interface{}, error) {
  577. vals, err := mv.ValuesForPath(path)
  578. if err != nil {
  579. return nil, err
  580. }
  581. if len(vals) == 0 {
  582. return nil, PathNotExistError
  583. }
  584. return vals[0], nil
  585. }
  586. // ValuesForPathString returns the first found value for the path as a string.
  587. func (mv Map) ValueForPathString(path string) (string, error) {
  588. vals, err := mv.ValuesForPath(path)
  589. if err != nil {
  590. return "", err
  591. }
  592. if len(vals) == 0 {
  593. return "", errors.New("ValueForPath: path not found")
  594. }
  595. val := vals[0]
  596. return fmt.Sprintf("%v", val), nil
  597. }
  598. // ValueOrEmptyForPathString returns the first found value for the path as a string.
  599. // If the path is not found then it returns an empty string.
  600. func (mv Map) ValueOrEmptyForPathString(path string) string {
  601. str, _ := mv.ValueForPathString(path)
  602. return str
  603. }