Giter Site home page Giter Site logo

mxj's People

Contributors

agrison avatar amansardana avatar anthonyfok avatar arxdsilva avatar candiduslynx avatar charl avatar clbanning avatar elyzov avatar eugzol avatar fatih avatar fkautz avatar fschr avatar gdbc avatar mrsln avatar slotix avatar tobiade avatar tomwright avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mxj's Issues

json.Number

Please add json.Number in func mapToXmlIndent.
Bcz mxj.AnyXmlIdent() not work properly. Example:


func main() {
    var data = `{"country_code": "US", "language_code": "en", "gatekeepers": {"sulgin": true}, "show_app_install": true, "static_root": "//instagramstatic-a.akamaihd.net/h1", "platform": "web", "hostname": "www.instagram.com", "entry_data": {"PostPage": [{"media": {"caption_is_edited": false, "code": "BDjodwSyGGq", "date": 1459297046, "dimensions": {"width": 480, "height": 480}, "usertags": {"nodes": []}, "comments_disabled": false, "comments": {"count": 0, "page_info": {"has_previous_page": false, "start_cursor": null, "end_cursor": null, "has_next_page": false}, "nodes": []}, "id": "1216994290900165034", "caption": "#\u043d\u0430\u0448\u0430\u0440\u0430\u0448\u0430 #\u043d\u0430\u0448\u0438\u043b\u044e\u0434\u0438 #\u0432\u0441\u0448\u0430 #\u043d\u0430\u0448\u0438\u0432\u0441\u0448\u0430 #\u0440\u0443\u0441\u0441\u043a\u0438\u0435\u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0446\u044b #\u044d\u043c\u0438\u0433\u0440\u0430\u043d\u0442\u044b #\u0431\u0438\u0437\u043d\u0435\u0441\u0434\u043b\u044f\u0432\u0441\u0435\u0445 #\u0440\u0435\u043a\u043b\u0430\u043c\u0430 #\u0434\u0432\u0438\u0433\u0430\u0442\u0435\u043b\u044c\u0442\u043e\u0440\u0433\u043e\u0432\u043b\u0438 #\u044d\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f #\u044d\u043c\u0438\u0433\u0440\u0430\u043d\u0442 \ud83d\udcf0\ud83d\udcf0\ud83d\udcf0", "likes": {"count": 43, "viewer_has_liked": false, "nodes": [{"user": {"username": "pldobedova.28a38", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/12930855_465421790323473_1556000816_a.jpg", "id": "3089391767"}}, {"user": {"username": "lowell.jamie", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/11856626_1037074359637483_999068832_a.jpg", "id": "2080739691"}}, {"user": {"username": "landing.page_phoenix", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/12445898_1531059877197403_1819456767_a.jpg", "id": "3077787572"}}, {"user": {"username": "sayvareli_dze", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/11032812_1584136531829418_1785931404_a.jpg", "id": "513392404"}}, {"user": {"username": "ay_santoscoy", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/14272205_1275392582495342_73128013_a.jpg", "id": "1649974424"}}, {"user": {"username": "prodvijenie.insta", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/11906088_548272111992346_1417441135_a.jpg", "id": "2215391262"}}, {"user": {"username": "artmedia_anapa", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/10358206_1553844208262789_373239023_a.jpg", "id": "1680807698"}}, {"user": {"username": "mariespb", "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/11325982_1451202301858508_2127601513_a.jpg", "id": "30643652"}}]}, "owner": {"username": "detroitexpress", "is_unpublished": false, "requested_by_viewer": false, "followed_by_viewer": false, "blocked_by_viewer": false, "profile_pic_url": "https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/12145014_544683419043251_2082408059_a.jpg", "full_name": "Detroit Express", "has_blocked_viewer": false, "id": "3053714631", "is_private": false}, "is_video": false, "is_ad": false, "display_src": "https://scontent-lga3-1.cdninstagram.com/t51.2885-15/s480x480/e35/12677559_212976009064620_1228847978_n.jpg?ig_cache_key=MTIxNjk5NDI5MDkwMDE2NTAzNA%3D%3D.2", "location": null}}]}, "qe": {"profile": {"p": {}, "g": ""}, "su_universe": {"p": {}, "g": ""}, "notif": {"p": {}, "g": ""}, "us": {"p": {"show_desktop_registration_upsell": "false"}, "g": "show_desktop_registration_upsell_05"}, "su": {"p": {"enabled": "true"}, "g": "rollout_20160325"}, "us_li": {"p": {}, "g": ""}, "discovery": {"p": {}, "g": ""}}, "display_properties_server_guess": {"viewport_width": 360, "pixel_ratio": 1.5}, "config": {"viewer": null, "csrf_token": "jKzHJyiHFEu7YqP6wFLJpc3UP4tST744"}, "environment_switcher_visible_server_guess": true}`
    mxj.JsonUseNumber = true
    var x interface{}
    dec := json.NewDecoder(bytes.NewReader([]byte(data)))
    dec.UseNumber()
    if err := dec.Decode(&x); err != nil {
        fmt.Printf("Unmarshal: %v", err)
    }
    xx, err := mxj.AnyXmlIndent(x, "", " ", "body")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(string(xx))

}

Will print:

<body>
    <config>
        <csrf_token>
            jKzHJyiHFEu7YqP6wFLJpc3UP4tST744
        </csrf_token>
        <viewer />
    </config>
    <country_code>
        US
    </country_code>
    <display_properties_server_guess>
        <Number>
            1.5
        </Number>
        <Number>
            360
        </Number>
    </display_properties_server_guess>
    <entry_data>
        <PostPage>
            <media>
                <caption>
                    #нашараша #нашилюди #всша #нашивсша #русскиеамериканцы #эмигранты #бизнесдлявсех #реклама #двигательторговли #эмиграция #эмигрант 📰📰📰
                </caption>
                <caption_is_edited>
                    false
                </caption_is_edited>
                <code>
                    BDjodwSyGGq
                </code>
                <comments>
                    <Number>
                        0
                    </Number>
                    <page_info>
                        <end_cursor />
                        <has_next_page>
                            false
                        </has_next_page>
                        <has_previous_page>
                            false
                        </has_previous_page>
                        <start_cursor />
                    </page_info>
                </comments>
                <comments_disabled>
                    false
                </comments_disabled>
                <Number>
                    1459297046
                </Number>
                <dimensions>
                    <Number>
                        480
                    </Number>
                    <Number>
                        480
                    </Number>
                </dimensions>
                <display_src>
                    https://scontent-lga3-1.cdninstagram.com/t51.2885-15/s480x480/e35/12677559_212976009064620_1228847978_n.jpg?ig_cache_key=MTIxNjk5NDI5MDkwMDE2NTAzNA%3D%3D.2
                </display_src>
                <id>
                    1216994290900165034
                </id>
                <is_ad>
                    false
                </is_ad>
                <is_video>
                    false
                </is_video>
                <likes>
                    <Number>
                        43
                    </Number>
                    <nodes>
                        <user>
                            <id>
                                3089391767
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/12930855_465421790323473_1556000816_a.jpg
                            </profile_pic_url>
                            <username>
                                pldobedova.28a38
                            </username>
                        </user>
                    </nodes>
                    <nodes>
                        <user>
                            <id>
                                2080739691
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/11856626_1037074359637483_999068832_a.jpg
                            </profile_pic_url>
                            <username>
                                lowell.jamie
                            </username>
                        </user>
                    </nodes>
                    <nodes>
                        <user>
                            <id>
                                3077787572
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/12445898_1531059877197403_1819456767_a.jpg
                            </profile_pic_url>
                            <username>
                                landing.page_phoenix
                            </username>
                        </user>
                    </nodes>
                    <nodes>
                        <user>
                            <id>
                                513392404
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/11032812_1584136531829418_1785931404_a.jpg
                            </profile_pic_url>
                            <username>
                                sayvareli_dze
                            </username>
                        </user>
                    </nodes>
                    <nodes>
                        <user>
                            <id>
                                1649974424
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/14272205_1275392582495342_73128013_a.jpg
                            </profile_pic_url>
                            <username>
                                ay_santoscoy
                            </username>
                        </user>
                    </nodes>
                    <nodes>
                        <user>
                            <id>
                                2215391262
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/11906088_548272111992346_1417441135_a.jpg
                            </profile_pic_url>
                            <username>
                                prodvijenie.insta
                            </username>
                        </user>
                    </nodes>
                    <nodes>
                        <user>
                            <id>
                                1680807698
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/10358206_1553844208262789_373239023_a.jpg
                            </profile_pic_url>
                            <username>
                                artmedia_anapa
                            </username>
                        </user>
                    </nodes>
                    <nodes>
                        <user>
                            <id>
                                30643652
                            </id>
                            <profile_pic_url>
                                https://scontent-lga3-1.cdninstagram.com/t51.2885-19/11325982_1451202301858508_2127601513_a.jpg
                            </profile_pic_url>
                            <username>
                                mariespb
                            </username>
                        </user>
                    </nodes>
                    <viewer_has_liked>
                        false
                    </viewer_has_liked>
                </likes>
                <location />
                <owner>
                    <blocked_by_viewer>
                        false
                    </blocked_by_viewer>
                    <followed_by_viewer>
                        false
                    </followed_by_viewer>
                    <full_name>
                        Detroit Express
                    </full_name>
                    <has_blocked_viewer>
                        false
                    </has_blocked_viewer>
                    <id>
                        3053714631
                    </id>
                    <is_private>
                        false
                    </is_private>
                    <is_unpublished>
                        false
                    </is_unpublished>
                    <profile_pic_url>
                        https://scontent-lga3-1.cdninstagram.com/t51.2885-19/s150x150/12145014_544683419043251_2082408059_a.jpg
                    </profile_pic_url>
                    <requested_by_viewer>
                        false
                    </requested_by_viewer>
                    <username>
                        detroitexpress
                    </username>
                </owner>
                <usertags>
                </usertags>
            </media>
        </PostPage>
    </entry_data>
    <environment_switcher_visible_server_guess>
        true
    </environment_switcher_visible_server_guess>
    <gatekeepers>
        <sulgin>
            true
        </sulgin>
    </gatekeepers>
    <hostname>
        www.instagram.com
    </hostname>
    <language_code>
        en
    </language_code>
    <platform>
        web
    </platform>
    <qe>
        <discovery>
            <g />
            <p />
        </discovery>
        <notif>
            <g />
            <p />
        </notif>
        <profile>
            <g />
            <p />
        </profile>
        <su>
            <g>
                rollout_20160325
            </g>
            <p>
                <enabled>
                    true
                </enabled>
            </p>
        </su>
        <su_universe>
            <g />
            <p />
        </su_universe>
        <us>
            <g>
                show_desktop_registration_upsell_05
            </g>
            <p>
                <show_desktop_registration_upsell>
                    false
                </show_desktop_registration_upsell>
            </p>
        </us>
        <us_li>
            <g />
            <p />
        </us_li>
    </qe>
    <show_app_install>
        true
    </show_app_install>
    <static_root>
        //instagramstatic-a.akamaihd.net/h1
    </static_root>
</body>

Bugfix m.XmlWriterRaw undefined

Package github.com/clbanning/mxj/j2x uses m.XmlWriterRaw removed on v1.8.4

github.com/clbanning/mxj/j2x
../clbanning/mxj/j2x/j2x.go:39:2: not enough arguments to return
../clbanning/mxj/j2x/j2x.go:39:10: m.XmlWriterRaw undefined (type mxj.Map has no field or method XmlWriterRaw)
../clbanning/mxj/j2x/j2x.go:58:17: m.XmlWriterRaw undefined (type mxj.Map has no field or method XmlWriterRaw)

https://github.com/clbanning/mxj/blob/master/j2x/j2x.go#L34-L40

https://github.com/clbanning/mxj/blob/master/j2x/j2x.go#L53-L60

getSubKeyMap

There seems to be a couple issues with this function.

Getting a runtime error: index out of range [recovered]
First the switch is on the length of the split string. If the length of the string array is 3 (case 3), then you can't reference vv[3] which would be the 4th element right? It must be vv[2] to access the third string.

Second, if your text has any ":" in it, it will get confused. My text had a "http://blah/blah/blah" in it. So, after I made the above change, I got the error: "unknown subkey conversion spec:..."

Basically I was trying to read in a kml file, change the description and name fields and then print it back out. I was trying to use the
paths= PathsForKey("description")
values =ValuesForPath(paths[0]).
UpdateValuesForPath(newVal, path[0], "description:"+value[0])
with a double loop in there to get all the paths and values. But, because description can have any kind of text, this will not be possible. Is there a better way of doing this?

Thanks,
Lorie

License question

Hi,

In your documentation, you state that the code is licensed under the BSD 3 clause license.
When I reviewed the license file, it states first your name and the MIT License and then Go Language followed by the BSD 3 clause license.

Both are perfectly cool licenses, but could you clear up which one is the one that you actually selected?

Thanks

FAIL: ExampleMap_Struct (0.00s)

Hi !

When I try to test your project, it fails in the current directory:

command: go test -buildmode pie -compiler gc -ldflags "-X github.com/clbanning/mxj/version=1.8.2 -extldflags '-Wl,-z,relro '"
testing: github.com/clbanning/mxj

----------- TestXMPPStreamTagSeq ...

<stream:stream
from='example.com'
xmlns="jabber:client"
xmlns:stream="http://etherx.jabber.org/streams"
version="1.0">
map[stream:stream:map[#attr:map[from:map[#seq:0 #text:example.com] xmlns:map[#seq:1 #text:jabber:client] xmlns:stream:map[#text:http://etherx.jabber.org/streams #seq:2] version:map[#text:1.0 #seq:3]]]]

stream:features


</stream:features>
map[stream:features:map[sm:map[#attr:map[xmlns:map[#seq:0 #text:urn:xmpp:sm:3]] #seq:1] bind:map[#attr:map[xmlns:map[#text:urn:ietf:params:xml:ns:xmpp-bind #seq:0]] #seq:0]]]

stream:stream
map[stream:stream:map[]]

--- FAIL: ExampleMap_Struct (0.00s)
got:
mapVal: mxj.Map{"private":"Somewhere over the rainbow", "int":4, "str":"now's the time", "float":3.14159, "bool":true}
strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:""}

want (unordered):
mapVal: mxj.Map{"int":4, "str":"now's the time", "float":3.14159, "bool":true, "private":"Somewhere over the rainbow"}
strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:""}

Thanks

Xml serialization time grows exponentially with size of map

map.Xml() time grows exponentially for large map.
For example if we read 1MB XML and serialize it back it take almost 20s and if we double the size (duplicate the xml nodes from same input) then time taken is almost 90s.

I tested with this xml (http://aiweb.cs.washington.edu/research/projects/xmltk/xmldata/data/mondial/mondial-3.0.xml) with following code.

package main

import (
	"fmt"
	"io/ioutil"
	"time"

	mxj "github.com/clbanning/mxj"
)

func main() {
	b, _ := ioutil.ReadFile("/tmp/large.xml")
	start := time.Now()
	m, _ := mxj.NewMapXml(b)
	fmt.Printf("XML Read time %v\n", time.Now().Sub(start))
	start = time.Now()
	b, _ = m.Xml()
	fmt.Printf("XML Write time %v\n", time.Now().Sub(start))
}

I debugged further and I think it is because of string concatenation (*s += ). I created a simple code to string concatenation and found that it is very slow as string grows. When I replaced it by bytes.Buffer.Read then there was significant improvement.

example of append

I can't figure out how to append to a list.
I want to change

<a>
  <b>1</b>
</a>

to

<a>
  <b>1</b>
  <b>2</b>
</a>

XML unexpected EOF

When using the http.Response.Body as a reader to pass to NewMapXMLReader, it fails to parse XML responses not ending with a line break.

Here a test showing the error: https://play.golang.org/p/ob6DnGUwtLx

I was able to fix it in my project using this wrapper over the http.Response.Body:

type xmlReader struct {
	r io.Reader
}

func (x xmlReader) Read(p []byte) (n int, err error) {
	n, err = x.r.Read(p)

	if err != io.EOF {
		return n, err
	}

	if len(p) == n {
		return n, nil
	}

	p[n] = ([]byte("\n"))[0]
	return n + 1, err
}

It's not pretty but it worked https://play.golang.org/p/bITvPyFHuZ6

Don't you think this should be managed by the mxj lib itself?

support rdf/xml

Thanks for the awesome library. It scratches the itch that I have for dynamically parsing XML perfectly.

However, if you try to parse an rdf/xml document with this library, you get an index out of bounds panic.

Parsing XML with comments gives incomplete result

I'm trying to parse an Apache Tomcat server.xml file, make updates and save it back to a file (in exactly the same structure & layout). I've been using NewMapXmlSeq followed by SetValueForPath and then XmlSeqIndent. Broadly speaking it works, updating the value as desired but when the content is resaved a large amount of the comment content is gone. Debugging the issue it looks like the content is lost at the time of import. I've attached a file to test with but the start of the file up until the root element (<Server...) will need to be stripped before the file is parsed (to avoid the no root issue). I've not been able to identify that I'm doing anything wrong in the processing but happy to hear if that is the case. Thanks.
server_xml.zip

invalid tag name in result from function Xml for custom data type

Here're the codes using version v1.8.4 of mxj:

package main

import (
	"fmt"
	"github.com/clbanning/mxj"
)

func main() {
	type Cdata string
	data, err := mxj.Map(map[string]interface{}{
		"data": Cdata("test"),
	}).Xml()
	if err != nil {
		panic(err)
	}
	fmt.Println(string(data))
}

And this outputs:

<Cdata>test</Cdata></data>

There's a invalid </data> tag in the result. What I really expects is:

<data>test</data>

Do I miss somthing?

XMLEscapeChars don't seem to be working

I have this:

mxj.XMLEscapeChars(true)
final, err := newImport.XmlSeq()
_, err = io.WriteString(fo, string(final))

The output file shows: <shortDescription>>0-2y</shortDescription>

The original source is: <shortDescription>&gt;0-2y</shortDescription>

and that is the way I want it output. Am I missing something?

Parsing partial data

Hi there,

I would like to know if there is way to parse partial data located in different places in the xml doc. For example, I want to got from

`<a>
        <b>
            <c>c</c>
            <d>d</d>
        </b>
        <e>
            <x>x</x>
            <y>y</y>
            <z>z</z>
        </e>
        <f>f</f>
        <g>g</g>
    </a>`

to

`<a>
        <b>
            <c>c</c>
        </b>
        <e>
            <x>x</x>
        </e>
    </a>`

Is there any easy way to do that plz?

Thanks in advance!

prints in tests

It seems to be a good idea to replace in tests fmt.Println to testing.T.Log. Because it's hard to look for my fail message during tests. What do you think?

Reading directly from reader will fail parse, but writing and reading again succeed

When getting the following perfectly valid XML (a response from PANW Wildfire component):
`

2.0
<file_info>
yes
b918d3b98f590d99ac3694b373958017256a22b4
PE
dd8e64991f68eeebb52c9947ea56f39a776185d1a076741533aa6843022c03b0
7f638f13d0797ef9b1a393808dc93b94
55296
</file_info>
<task_info>

3.0
2
Windows XP, Adobe Reader 9.4.0, Flash 10, Office 2007
dd8e64991f68eeebb52c9947ea56f39a776185d1a076741533aa6843022c03b0
7f638f13d0797ef9b1a393808dc93b94
55296
yes

This is a WildFire test sample Created or modified a file in the Windows system folder Created or modified a file Modified the Windows Registry Created Process c:\documents and settings\administrator\sample.exe Set key \REGISTRY\MACHINE\SOFTWARE\PaloAlto\PanCar to value 1 3.0 5 Windows 7 x64 SP1, Adobe Reader 11, Flash 11, Office 2010 dd8e64991f68eeebb52c9947ea56f39a776185d1a076741533aa6843022c03b0 7f638f13d0797ef9b1a393808dc93b94 55296 yes This is a WildFire test sample Created or modified a file Modified the Windows Registry Created Process C:\Users\Administrator\sample.exe Set key \REGISTRY\MACHINE\SOFTWARE\Wow6432Node\PaloAlto\PanCar to value 1 3.0 204 PE Static Analyzer dd8e64991f68eeebb52c9947ea56f39a776185d1a076741533aa6843022c03b0 7f638f13d0797ef9b1a393808dc93b94 no Contains an invalid checksum Contains sections with size discrepancies ` And using the following function: `func ParseXMLResponseToJSON(reader io.Reader, resEntry *domain.Entry) error { b, err := ioutil.ReadAll(reader) if err != nil { return err } fmt.Println(string(b)) reader = bytes.NewReader(b) m, err := mxj.NewMapXmlReader(reader) if err != nil { return err } content, err := json.Marshal(m) if err != nil { return err } return string(content) }` I get the response in json. However, when I read direcly from the reader: `func ParseXMLResponseToJSON(reader io.Reader, resEntry *domain.Entry) error { /*b, err := ioutil.ReadAll(reader) if err != nil { return err } fmt.Println(string(b))*/ reader = bytes.NewReader(b) m, err := mxj.NewMapXmlReader(reader) if err != nil { return err } content, err := json.Marshal(m) if err != nil { return err } return string(content)` I get the following error: `xml.Decoder.Token() - XML syntax error on line 135: unexpected EOF`

Name space prefix syntax.

I just changed the XmlSeq parser to preserve name space prefixes as part of the key as well as preserving "xmlns:" in the attribute label. This lets you re-encode a Map value correctly when the original XML used name space qualified tags.

Is there a case to make this functionality part of the standard Xml parser - NewMapXml(), etc.?

When marshal with map[string]string, it gave me ">UNKNOWN/>"

Hi there, mxj is a great project and I've been using it in my gf project in XML marshal/unmarshal. It worked quite well with map[string]interface{} type, but when the parameter contains other map type (eg: map[string]string/map[string]int etc...), it failed working.

Here's the simple codes to reproduce this issue:

package main

import (
    "fmt"
    "github.com/clbanning/mxj"
)

func main() {
    m := make(map[string]interface{})
    m["m"] = map[string]string {
        "k" : "v",
    }
    b, _ := mxj.Map(m).Xml()
    fmt.Println(string(b))
}

It's supposed to give me {"m":{"k":"v"}} , but actually I got >UNKNOWN/>.

Would you please take a look, and kindly give me a nice feedback, thanks!

NewMapXmlSeq: 'no root key'' error if there is a XML declaration

I use the following XML for umarshaling it into a MapSeq. If there is a XML declaration (<?xml version="1.0" encoding="UTF-8"?>) the NewMapXmlSeq function returns the no root key error.

What made me wonder, is that if I use the exact same XML with NewMapXml all works without problems.

Any idea what could be wrong here?

Used XML:

<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
    <responseDate>2019-08-06T14:09:14Z</responseDate>
</OAI-PMH>

Convert `ValueForKey` result to `Map`

Is it possible to select an XML node using one of the ValueFor... methods and then work with it as with root node?

I've tried following:

mv, err := mxj.NewMapXml([]byte(sample_xml))

if err != nil {
    log.Printf("Error parsing XML data: %v\n", err)
} else {
    tst, _ := mv.ValueForKey("some-tag")
    if mv2, ok := tst.(mxj.Map); ok {
        xmlStr, _ := mv2.XmlIndent("====", "    ")
        log.Printf("Pretty XML:\n")
        log.Printf("%s\n", xmlStr)
    } else {
        log.Printf("Error: Cant convert tst to map[string]interface{}\n")
    }
}

But getting the Error: Cant convert tst to map[string]interface{} output.

Probably missing something obvious from the docs here...Any pointers as to what?

Build issues

mxj isn't building currently. Here's what I get...

$ go get github.com/clbanning/mxj
# github.com/clbanning/mxj
src/github.com/clbanning/mxj/xml.go:471:40: cannot convert t (type xml.Token) to type string: need type assertion
markbr@A31217MarkBr:~/test$ 

github.com/clbanning/mxj/examples/gonuts9.go:8:2: cannot find package "tamgroup/mxj"

the follwing error happens with go get on projects that include clbanning/mxj
github.com/clbanning/mxj/examples/gonuts9.go:8:2: cannot find package "tamgroup/mxj"

also:
github.com/clbanning/mxj/examples
github.com/clbanning/mxj/examples/getmetrics1.go:47: main redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/books.go:36
github.com/clbanning/mxj/examples/getmetrics2.go:48: main redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/getmetrics1.go:47
github.com/clbanning/mxj/examples/getmetrics3.go:49: main redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/getmetrics2.go:48
github.com/clbanning/mxj/examples/getmetrics4.go:50: main redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/getmetrics3.go:49
github.com/clbanning/mxj/examples/gonuts1.go:39: main redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/getmetrics4.go:50
github.com/clbanning/mxj/examples/gonuts1a.go:26: msg1 redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/gonuts1.go:26
github.com/clbanning/mxj/examples/gonuts1a.go:37: msg2 redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/gonuts1.go:37
github.com/clbanning/mxj/examples/gonuts1a.go:39: main redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/gonuts1.go:39
github.com/clbanning/mxj/examples/gonuts2.go:62: main redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/gonuts1a.go:39
github.com/clbanning/mxj/examples/gonuts3.go:24: xmldata redeclared in this block
previous declaration at github.com/clbanning/mxj/examples/books.go:34
github.com/clbanning/mxj/examples/gonuts3.go:24: too many errors

Locate and modify

Related to issue #28, what I am looking forward to in mxj, is able to locate some records according to XPath/JPath or something similar, them modify the located record.

Please take a look at this .xml file for example, I need to, expressed in xpath term,

  • locate //Request nodes; and for each node found,
  • change its attribute according to other attributes.

For example, these changes were to change

//Request's ./[ReportingName] use the basename of ./[Url]( and prefix with ../TransactionTimer[Name] as well, but that's a bonus request if it is too difficult at first).

The final result is posted here.

How can I do that? Thx.

j2x does not encode < > &

Hi,

It seems like special xml characters don't get encoded:

Test case:
json := "{ \"test\": \"a&b <c>\" }"
xml, _ := j2x.JsonToXml([]byte(json))
fmt.Printf("xml %v\n", string(xml))

Output:
xml <test>a&b <c></test>

How can we encode these values?

Cannot remove element from XML array

I'm trying to manipulate an XML file similar to the following example (simplified):

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://example.com" catalog-id="my-catalog">
    <product product-id="a">
        <online-flag>false</online-flag>
        <available-flag>true</available-flag>
    </product>

    <product product-id="b">
        <online-flag>true</online-flag>
        <available-flag>true</available-flag>
    </product>
</catalog>

Essentially I want to remove any <product> where <online-flag> is set to false and output a new XML file reflecting those changes. Here's the code I'm using to try to accomplish that:

package main

import (
	"log"
	"os"
	"strconv"

	"github.com/clbanning/mxj"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func main() {
	catalogXML, err := os.Open("catalog_example.xml")
	check(err)
	defer catalogXML.Close()

	mv, err := mxj.NewMapXmlReader(catalogXML)
	check(err)

	item, err := mv.ValuesForPath("catalog.product")
	check(err)

	total := 0
	online := 0

	for i, v := range item {
		data := v.(map[string]interface{})

		if data["online-flag"] == "true" {
			online++
		} else {
			path := "catalog.product[" + strconv.Itoa(i) + "]"
			log.Println("removing", path)
			getpid, err := mv.ValueForPath(path)
			check(err)
			log.Println(getpid)

			err = mv.Remove(path)
			check(err)
		}

		total++
	}

	catalogXMLReduced, err := os.Create("catalog_reduced.xml")
	check(err)
	defer catalogXMLReduced.Close()

	err = mv.XmlWriter(catalogXMLReduced)
	check(err)

	log.Println(online, "online /", total, "total")
}

Here's the output:

2020/09/01 00:43:33 removing catalog.product[0]
2020/09/01 00:43:33 map[-product-id:a available-flag:true online-flag:false]
panic: prevValueByPath: didn't find path – product[0]

goroutine 1 [running]:
main.check(...)
        main.go:13
main.main()
        main.go:44 +0x630

It would appear as though the path notation I'm using to reference the specific product key is supported in ValueForPath(), but throws an error when used with Remove().

Edge case for XML conversion

When converting from XML to a map I have found that a string value of "NAN", gets cast to a float value as a NaN. This is not the desired result in this particular case, as it is actually a string value.

There is no NaN equivalent in JSON, so when converting from a Map to JSON, I get an error:
json: unsupported value: NaN

I assume this issue would also arise if there was a string value of "Inf" or "-Inf".

I have written a small example below to replicate the issue.

package main

import (
    "fmt"

    "github.com/clbanning/mxj"
)

func main() {
    var xml = []byte("<foo><bar>NAN</bar></foo>")

    m, err := mxj.NewMapXml(xml, true)
    if err != nil {
        panic(err)
    }

    fmt.Print(m.StringIndent())
    fmt.Println()

    j, err := m.JsonIndent("", "  ", true)
    if err != nil {
        panic(err)
    }

    fmt.Print(string(j))
}

Different results of conversion when there are attributes in the XML node.

I have the following XML:

<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
    <channel>
        <item>
            <g:id>30102</g:id>
            <g:title>Mini Drone Inteligente - Branco</title>
            <g:price unit="BRL">149.90</g:price>
        </item>
    </channel>
</rss>

After parsing XML I got the result:

map[
    title:Mini Drone Inteligente - Branco 
    id:30102 
    price:map[-unit:BRL #text:219.90] 
]

Notice that the fields had differently results of each other, price had result differently from others.
How I can get the same result for all fields? Like below:

map[
    title:map[#text: Mini Drone Inteligente - Branco]
    id:map[#text: 30102 ]
    price:map[-unit:BRL #text:219.90] 
]

Parse XML without closing tag

Hello.

I'm trying to use library to parse XMPP stream.

This is can be done quite simple with HandleXmlReader and NewXmlMapReader but since everything is going after <stream:stream> until it'll be closed parser just got stuck.

If it's not possible to handle continuous streams I just want to skip starting tag and continue from next one. So at least passing startElement to begin parse with next token will be a fine solution.

Format error after map converted to XML

package main

import (
	"fmt"
	"github.com/clbanning/mxj"
	"testing"
)

type ItemInfo struct {
	Id 	int 	`xml:"Id"`
	Name 	string 	`xml:"Name"`
}

func TestXmlToMap(t *testing.T) {
	items :=  make([]ItemInfo, 2)
	items[0].Id = 1
	items[0].Name = "item_name_1"
	items[1].Id = 2
	items[1].Name = "item_name_2"
	data := map[string]interface{}{
		"InvoDesc": "desc",
		"Orders": map[string]interface{}{
			"Order":map[string]interface{}{
				"BillNo":"billno",
				"Items":map[string]interface{}{
					"Item":items,
					//"Item":[]map[string]interface{} {{"Id":1, "Name":"item_name_1"},	{"Id":2, "Name":"item_name_2"}},
				},
			},
		},
	}


	mxjXmlStr, err := mxj.Map(data).Xml("InvoInfo")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("mxj Xml: ", string(mxjXmlStr))
}

Results after implementation is

<InvoInfo><InvoDesc>desc</InvoDesc><Orders><Order><BillNo>billno</BillNo><Items><ItemInfo><Id>1</Id><Name>item_name_1</Name></ItemInfo><ItemInfo><Id>2</Id><Name>item_name_2</Name></ItemInfo></Item></Items></Order></Orders></InvoInfo>

The expected result is

<InvoInfo><InvoDesc>desc</InvoDesc><Orders><Order><BillNo>billno</BillNo><Items><ItemInfo><Id>1</Id><Name>item_name_1</Name></ItemInfo><ItemInfo><Id>2</Id><Name>item_name_2</Name></ItemInfo></Items></Order></Orders></InvoInfo>

Please help to see where there is a mistake

Inner Tag Ordering

Is there any way to get the ordering of inner tags, if they are variable in their tag name?

For example:

Obj
Attr3
Attr1
Attr2
Obj

This ends up a map

{Obj:{Attr1:"",Attr2:"",Attr3:""}}, and there is no way to tell that the order was 3,1,2. I've run into a situation where I need to know the order, is there some flag or something that would allow me to turn the attributes into an ordered array, or to write out the order the parser ran into them as an attribute or something?

mxj/x2j is advertived as a migration path from x2J however it is missing functions like ByteDocToMap

Existing x2j users like
https://github.com/hudl/fargo/blob/master/metadata.go#L50

expect x2j.ByteDocToMap to exist

    // XML: wrap in a BS xml tag so all metadata tags are pulled
    fullDoc := append(append([]byte("<d>"), im.Raw...), []byte("</d>")...)
    parsedDoc, err := x2j.ByteDocToMap(fullDoc, true)
    if err != nil {
      log.Errorf("Error unmarshalling: %s", err.Error())
      return fmt.Errorf("error unmarshalling: %s", err.Error())
    }
    im.parsed = parsedDoc["d"].(map[string]interface{})

Go 1.10: anyxml_test.go:10: Println arg list ends with redundant newline

Release 1.6.1 does not pass unit tests with Go 1.10. At least:

+ GOPATH=/builddir/build/BUILD/mxj-1.6.1/_build:/usr/share/gocode
+ go test -buildmode pie -compiler gc -ldflags '-extldflags '\''-Wl,-z,relro  '\'''
# github.com/clbanning/mxj
./anyxml_test.go:10: Println arg list ends with redundant newline
./badxml_test.go:24: Println arg list ends with redundant newline
./bom_test.go:22: Println arg list ends with redundant newline
./bulk_test.go:12: Println arg list ends with redundant newline
./bulkraw_test.go:12: Println arg list ends with redundant newline
./files_test.go:9: Println arg list ends with redundant newline
./j2x_test.go:11: Println arg list ends with redundant newline
./json_test.go:15: Println arg list ends with redundant newline
./keyvalues_test.go:13: Println arg list ends with redundant newline
./keyvalues_test.go:227: Println arg list ends with redundant newline
./mxj_test.go:9: Println arg list ends with redundant newline
./namespace_test.go:9: Println arg list ends with redundant newline
./nan_test.go:11: Println arg list ends with redundant newline
./newmap_test.go:11: Println arg list ends with redundant newline
./seqnum_test.go:29: Println arg list ends with redundant newline
./struct_test.go:9: Println arg list ends with redundant newline
./updatevalues_test.go:11: Println arg list ends with redundant newline
./xml2_test.go:13: Println arg list ends with redundant newline
./xml_test.go:11: Println arg list ends with redundant newline
./xmlseq_test.go:10: Println arg list ends with redundant newline
FAIL    github.com/clbanning/mxj [build failed]

[Bug]integer will be transformed to double

Input json:
"ipv4": { "address-mode": "manual", "address": { "ip": "10.10.10.10", "prefix-length": 30 }

Output xml:
<ipv4><address><ip>10.0.22.14</ip><prefix-length>30.000000</prefix-length></address><address-mode>manual</address-mode><enabled>true</enabled><mtu>1500.000000</mtu><vti_peer>10.10.10.10</vti_peer></ipv4>

In this case, prefix-length:30 became 30.000000
Do anyone have the same problem with me?

UpdateValuesForPath not working as expected - proposed fix.

I found another issue. Attached is the testcase. So, I read in the kml file and wanted to find all the description tags and change their values. And, some of the values did not change. If you run the code as is you will see the errors:

ERROR Value not updated. Path=kml.Document.Folder.Placemark.description, oldVal=description!]?:@#Click on the blue link!

Placemark descriptions can be enriched by using many standard HTML tags.
, newVal=description!]?:@#Click on the blue link!<br><br>

Placemark descriptions can be enriched by using many standard HTML tags.<br> CHANGED

ERROR Value not updated. Path=kml.Document.Folder.Document.description, oldVal=description!]?:@#Place your mouse over the icon to see it display the new

icon, newVal=description!]?:@#Place your mouse over the icon to see it display the new

icon CHANGED

ERROR Value not updated. Path=kml.Document.description, oldVal=description!]?:@#Unleash your creativity with the help of these examples!, newVal=description!]?:@#Unleash your creativity with the help of these examples! CHANGED

The function that I call to change all the values is :
kmlMap.UpdateValuesForPath(newVal, path, oldVal)

If I go to function updateValue() which is called by UpdateValuesForPath(), and change the line 199 from:

if len(subkeys) == 0 {

====== TO =========

if hasSubKeys(m, subkeys) {

Then the errors go away and all the descriptions are changed. Now, there is also another place in that function that calls "len(subkeys)==0" on line 177. My sample data doesn't take me into that branch of code. But, I assume that if line 199 needs to be changed, then line 178 does too.

This line ("len(subkeys)==0") is also called three times in keyvalues.go in other functions. Does it need to be changed there as well?

Conversion from a null element to <element/> is broken

I got the following example

package main

import (
	"github.com/clbanning/mxj"
	"encoding/json"
	"fmt"
	"bytes"
)

func main() {
	var data = `{"lastname":"Mustermann","phone": null}"`

	mxj.JsonUseNumber = true
	var x interface{}
	dec := json.NewDecoder(bytes.NewReader([]byte(data)))
	dec.UseNumber()
	if err := dec.Decode(&x); err != nil {
		fmt.Printf("Unmarshal: %v", err)
	}
	xx, err := mxj.AnyXmlIndent(x, "", " ", "body")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(xx))

}

Expected result is an empty phone element

<body>
 <lastname>Mustermann</lastname>
<phone/>
</body>

This is working in commit 1db1a88

but broken from commit adfeeb9

From this commit up to current master, we got this result

<body>
 <lastname>Mustermann</lastname>
<phone
</body>

Out of memory error when handling malformed http.Request Body

I have the following minimal example:

// main.go
package main

import (
	"net/http"
	"strings"

	"github.com/clbanning/mxj"
)

func main() {
	request, _ := http.NewRequest("POST", "/endpoint", strings.NewReader("not an XML"))
	_, _ = mxj.NewMapXmlReader(request.Body)
}

Running it (go run main.go) gives fatal error: runtime: out of memory after some seconds of freezing.

Full output:

fatal error: runtime: out of memory

runtime stack:
runtime.throw(0x6460b0, 0x16)
        /usr/local/go/src/runtime/panic.go:566 +0x95
runtime.sysMap(0xc4a2210000, 0x82000000, 0x0, 0x769fd8)
        /usr/local/go/src/runtime/mem_linux.go:219 +0x1d0
runtime.(*mheap).sysAlloc(0x750da0, 0x82000000, 0x40dc00)
        /usr/local/go/src/runtime/malloc.go:407 +0x37a
runtime.(*mheap).grow(0x750da0, 0x41000, 0x0)
        /usr/local/go/src/runtime/mheap.go:726 +0x62
runtime.(*mheap).allocSpanLocked(0x750da0, 0x41000, 0xc4200001a0)
        /usr/local/go/src/runtime/mheap.go:630 +0x4f2
runtime.(*mheap).alloc_m(0x750da0, 0x41000, 0x7f0100000000, 0x7fe848aece10)
        /usr/local/go/src/runtime/mheap.go:515 +0xe0
runtime.(*mheap).alloc.func1()
        /usr/local/go/src/runtime/mheap.go:579 +0x4b
runtime.systemstack(0x7fe848aece18)
        /usr/local/go/src/runtime/asm_amd64.s:314 +0xab
runtime.(*mheap).alloc(0x750da0, 0x41000, 0x10100000000, 0xc420010ff0)
        /usr/local/go/src/runtime/mheap.go:580 +0x73
runtime.largeAlloc(0x81ffffff, 0xc420010f01, 0xc42004f120)
        /usr/local/go/src/runtime/malloc.go:774 +0x93
runtime.mallocgc.func1()
        /usr/local/go/src/runtime/malloc.go:669 +0x3e
runtime.systemstack(0xc420020a00)
        /usr/local/go/src/runtime/asm_amd64.s:298 +0x79
runtime.mstart()
        /usr/local/go/src/runtime/proc.go:1079

goroutine 1 [running]:
runtime.systemstack_switch()
        /usr/local/go/src/runtime/asm_amd64.s:252 fp=0xc42004f028 sp=0xc42004f020
runtime.mallocgc(0x81ffffff, 0x5ef6e0, 0xc42004f101, 0x44fb40)
        /usr/local/go/src/runtime/malloc.go:670 +0x903 fp=0xc42004f0c8 sp=0xc42004f028
runtime.makeslice(0x5ef6e0, 0x81ffffff, 0x81ffffff, 0x72d880, 0xc42000c150, 0xc42004f190)
        /usr/local/go/src/runtime/slice.go:57 +0x7b fp=0xc42004f120 sp=0xc42004f0c8
bytes.makeSlice(0x81ffffff, 0x0, 0x0, 0x0)
        /usr/local/go/src/bytes/buffer.go:198 +0x77 fp=0xc42004f160 sp=0xc42004f120
bytes.(*Buffer).grow(0xc42008c730, 0x1, 0x4c00000040fffffe)
        /usr/local/go/src/bytes/buffer.go:106 +0x178 fp=0xc42004f1b0 sp=0xc42004f160
bytes.(*Buffer).WriteByte(0xc42008c730, 0x14c, 0x0, 0x0)
        /usr/local/go/src/bytes/buffer.go:235 +0x3c fp=0xc42004f1d8 sp=0xc42004f1b0
encoding/xml.(*Decoder).text(0xc42008c6e0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/encoding/xml/xml.go:1076 +0x106 fp=0xc42004f388 sp=0xc42004f1d8
encoding/xml.(*Decoder).rawToken(0xc42008c6e0, 0xc42004fb10, 0x4649a4, 0x600780, 0xc4200109c0)
        /usr/local/go/src/encoding/xml/xml.go:525 +0x2b43 fp=0xc42004f778 sp=0xc42004f388
encoding/xml.(*Decoder).Token(0xc42008c6e0, 0xc420010a20, 0x7, 0xc42004fac0, 0x408334)
        /usr/local/go/src/encoding/xml/xml.go:249 +0x1484 fp=0xc42004f9c0 sp=0xc42004f778
github.com/clbanning/mxj.xmlToMapParser(0x0, 0x0, 0x0, 0x0, 0x0, 0xc42008c6e0, 0x0, 0x5caa11, 0x18, 0x28)
        /home/eugzol/Projects/go/src/github.com/clbanning/mxj/xml.go:311 +0xa5 fp=0xc42004fda0 sp=0xc42004f9c0
github.com/clbanning/mxj.xmlReaderToMap(0x72d8c0, 0xc420010f60, 0x0, 0xc42000cfdf, 0x1, 0x1)
        /home/eugzol/Projects/go/src/github.com/clbanning/mxj/xml.go:140 +0x240 fp=0xc42004fe80 sp=0xc42004fda0
github.com/clbanning/mxj.NewMapXmlReader(0x7fe84aa4e058, 0xc42000d090, 0x0, 0x0, 0x0, 0xc4200cc820, 0xc4200d00f0, 0x0)
        /home/eugzol/Projects/go/src/github.com/clbanning/mxj/xml.go:86 +0x96 fp=0xc42004fee8 sp=0xc42004fe80
main.main()
        /home/eugzol/Projects/go/src/github.com/MyceliumGear/test/main.go:12 +0x104 fp=0xc42004ff48 sp=0xc42004fee8
runtime.main()
        /usr/local/go/src/runtime/proc.go:183 +0x1f4 fp=0xc42004ffa0 sp=0xc42004ff48
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc42004ffa8 sp=0xc42004ffa0

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2086 +0x1
exit status 2

Go version: go version go1.7.1 linux/amd64

NewMapXml() simplifies single item arrays into items

Hi,

Many thanks for writing and especially for maintaining the package.

When running NewMapXml() with an XML containing 2 or more items it results an []interface{} of the items, otherwise only the item (mostly map[string]interface{}), see below:

package main

import (
	"fmt"
	"io"
	"reflect"

	"github.com/clbanning/mxj"
)

func main() {
	type Map map[string]interface{}
	x := []byte(`<doc> 
		    <book>
			<author>A</author>
		    </book>
		    <book>
			<author>B</author>
		    </book>
                </doc>`)
	y := []byte(`<doc> 
		    <book>
			<author>A</author>
		    </book>
                </doc>`)

	m, err := mxj.NewMapXml(x)
	if err != nil && err != io.EOF {
		panic(err)
	}
	n, err := mxj.NewMapXml(y)
	if err != nil && err != io.EOF {
		panic(err)
	}
	m1 := reflect.ValueOf(m["doc"])
	n1 := reflect.ValueOf(n["doc"])
	if m1.MapIndex(m1.MapKeys()[0]) != n1.MapIndex(n1.MapKeys()[0]) {
		fmt.Printf("%#v != %#v", m1, n1)
	}
}

Tested it with go 1.10.1 and 1.7.0

UNKNOWN in XML collection

We currently have a use case where we take a large XML payload and convert it to JSON for manipulation and then convert it back to XML. An example payload:

<Message source="RDC" target="IDC" type="CWCUSTHISTOUT">
    <Headers>
        <Header company_code="1" order_id="123" reference_order_number="fff123" customer_number="123" order_date="09202016" order_channel="E" bill_me_later_ind="N">
            <ShipTos><ShipTo ship_to_number="1" ship_to_status="X" gift_order="N" ship_via_code="1" ship_via_description="FEDEX HOME" shipping_override="N"/></ShipTos>
        </Header>
        <Header company_code="1" order_id="123" customer_number="123" order_date="05092013" bill_me_later_ind="N">
            <ShipTos><ShipTo ship_to_number="1" sub_total="138.50" shipping="11.95" tax="13.55" order_total="164.00" ship_to_status="X" gift_order="N" ship_via_code="1" ship_via_description="FEDEX HOME" shipping_override="N"/></ShipTos>
        </Header>
    </Headers>
</Message>

The resulting JSON is fine:

{
    "Message": {
        "-source": "RDC",
        "-target": "IDC",
        "-type": "CWCUSTHISTOUT",
        "Headers": {
            "Header": [{
                "-bill_me_later_ind": "N",
                "-company_code": "1",
                "-customer_number": "123",
                "-order_channel": "E",
                "-order_date": "09202016",
                "-order_id": "123",
                "-reference_order_number": "fff123",
                "ShipTos": {
                    "ShipTo": {
                        "-gift_order": "N",
                        "-ship_to_number": "1",
                        "-ship_to_status": "X",
                        "-ship_via_code": "1",
                        "-ship_via_description": "FEDEX HOME",
                        "-shipping_override": "N"
                    }
                }
            }, {
                "-bill_me_later_ind": "N",
                "-company_code": "1",
                "-customer_number": "123",
                "-order_date": "05092013",
                "-order_id": "123",
                "ShipTos": {
                    "ShipTo": {
                        "-gift_order": "N",
                        "-order_total": "164.00",
                        "-ship_to_number": "1",
                        "-ship_to_status": "X",
                        "-ship_via_code": "1",
                        "-ship_via_description": "FEDEX HOME",
                        "-shipping": "11.95",
                        "-shipping_override": "N",
                        "-sub_total": "138.50",
                        "-tax": "13.55"
                    }
                }
            }]
        }
    }
}

The issue occurs when parsing it back to XML:

<Message source="RDC" target="IDC" type="CWCUSTHISTOUT"><Headers>>UNKNOWN/></Headers></Message>

With a little digging the following error is being generated here:

xml: unsupported type: map[string]interface {}

All XML elements are unmarshalled with quotes as strings

I don't know if this is the intended behavior, but mxj.NewMapXml() seem to unmarshal all XML elements to a string. In my case I'd have expected at least integers and bool values to be unmarshalled without quotes.

Here's an example to help illustrate the problem: http://play.golang.org/p/ZhGqn4EWHD

Otherwise I like this package, and perhaps I'll do a fork to implement this functionality, if it's not already there (undocumented) - it should be fairly easy to decide if the value is a string, int or bool, and for other types we would even add an attribute on the element to check against.

Again I don't know if this functionality is left out intentionally since perhaps you do not consider this a responsibility for this package, but something we should handle in our own code?

Replace Hypen with standard Javascript Character

This is a great library! Thanks for making this. When converting XML to JSON should we be using a Hypen for attributes? Why not use an underscore? The reason being is that this library is highly useful for server side processing where it concerns Javascript...so turning that JSON into a POJO would be better aligned using an underscore...unfortunately the $ sign is way to overused.

Failed to parse xml to map when attributes contain special characters (&, >, <, ', ")

Hi @clbanning , I have xml document below and got error xml.Decoder.Token() - XML syntax error on line 2: invalid character entity & (no semicolon) when parsing xml to map:

<document> <name>Bill & Hallett</name> <salute>Duc &amp; 123xx</salute> <goes_by/> <lang>E</lang> </document>

Just read your code, and found problem at xmlToMapParser function. You're using xml.Decoder with Strict=true by default that dose not allow special characters (https://golang.org/pkg/encoding/xml/#Decoder)

Could you fix it or expose some ways to enable/disable Strict mode from xm.Decoder object?

Proposal for adding capability to skip conversion for specific keys

Thanks for the great library, it is of great help.
I have a use case, In which I need to skip casting of value for few keys to numeric/bool.
We can provide a function which takes in a regex/list of keys and sets them to skip casting for those keys.
Please let me know, what you think, I can write the function for this, and create a pull request.

NewMapXmlSeq process instructions

hi,

I'm dealing with some XML files that have <?xml version="1.0" encoding="utf-8"?> at top of the file by using the NewMapXmlSeq cause I want to preserve the format and some comments in the file.

But I could only get the result map[#procinst:map[#target:xml #inst:version="1.0" encoding="utf-8"]],
and the returned error is no root key

As you mentioned in the doc:

comments, directives, and procinsts that are NOT part of a document with a root key will be returned as
  map[string]interface{} and the error value 'NoRoot'.

How can I get the whole map of the XML file?
I thought it's quite common that <?xml version="1.0" encoding="utf-8"?> not belong to any root

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.