Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added named struct extraction flag #21

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fe02594
added named struct extraction flag
periode May 26, 2022
58e68f1
Opensource wasm alternative https://xml-to-go.github.io/
YaroslavPodorvanov Aug 23, 2022
25aa987
Merge pull request #23 from YaroslavPodorvanov/xml-to-go.github.io
miku Aug 23, 2022
bb6b75a
update deps
miku Sep 14, 2022
a56b3a8
update README
miku Jan 9, 2023
9ddf8d3
add related project
miku Jan 17, 2023
70ef6b4
update deps
miku Oct 24, 2022
395c64d
v0.1.17
miku Oct 24, 2022
b403fd3
update deps
miku Feb 21, 2023
d501f2a
v0.1.18
miku Feb 21, 2023
54000d0
update go.sum
miku Feb 21, 2023
9eb1980
update README
miku Mar 14, 2023
23bc7e7
update link
miku Mar 20, 2023
b26495f
v0.1.19
miku Apr 10, 2023
f668fc0
update makefile
miku Apr 10, 2023
3df0e26
prepare readAtMost flag
miku Aug 2, 2023
1b33330
feature: add flag to limit bytes read
miku Aug 2, 2023
6fc5f17
v0.1.20
miku Aug 2, 2023
b5730ec
fix: switch from max bytes read to max tokens read
miku Aug 2, 2023
a6e1ccf
v0.1.21
miku Aug 2, 2023
e073a77
just run tests
YaroslavPodorvanov Jan 2, 2024
ea18cab
change branch name for actions
YaroslavPodorvanov Jan 2, 2024
f29866e
Merge pull request #28 from doutivity/run-tests
miku Jan 2, 2024
5a5c703
go.mod: update required version
miku Jan 2, 2024
c560c10
go.mod: minimal go version is 1.16
miku Jan 2, 2024
202e712
update deps
miku Jan 2, 2024
a1ad2e1
use go 1.17 (build tags)
miku Jan 3, 2024
5d3a432
fix go.mod
miku Jan 3, 2024
3386376
added named struct extraction flag
periode May 26, 2022
f911d47
feature: flag to not inline the structs
periode Jan 21, 2024
b311916
merge branch 'master' of github.com:periode/zek
periode Jan 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/code_quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Code quality

on:
push:
branches:
- master

jobs:
code-quality:
name: Code quality
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.17'

- name: Unit tests
run: go test -v ./...
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ SHELL = /bin/bash
TARGETS = zek
PKGNAME = zek
ARCH = amd64
VERSION = 0.1.16
VERSION = 0.1.21

.PHONY: all
all: $(TARGETS)
Expand Down Expand Up @@ -52,7 +52,7 @@ rpm: $(TARGETS) docs/$(PKGNAME).1

.PHONY: release
release:
@export GITHUB_TOKEN="..."
@echo export GITHUB_TOKEN="..."
@echo go tag $(VERSION)
@echo goreleaser release --rm-dist

Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ type Rss struct {

## Online

Try it online at [https://www.onlinetool.io/xmltogo/](https://www.onlinetool.io/xmltogo/) -- thanks, [kjk](https://github.com/kjk)!
* try online via WASM: [https://xml-to-go.github.io/](https://xml-to-go.github.io/), thanks [YaroslavPodorvanov](https://github.com/YaroslavPodorvanov)!
* try it online at [https://blog.kowalczyk.info/tools/xmltogo/](https://blog.kowalczyk.info/tools/xmltogo/) -- thanks, [kjk](https://github.com/kjk)!

## About

Expand All @@ -98,7 +99,7 @@ Downsides:

* experimental, early, buggy, unstable prototype,
* no support for recursive types (similar to *Russian Doll* strategy, [[1](https://medbiq.org/std_specs/techguidelines/xmldesignguidelines.pdf#page=7)])
* no type inference, everything is accessible as string.
* no type inference, everything is accessible as string (without a schema, type inference may fail if the type *guess* is wrong)

Bugs:

Expand All @@ -113,6 +114,7 @@ Related projects:
* https://github.com/bemasher/JSONGen
* https://github.com/dutchcoders/XMLGen
* https://github.com/gnewton/chidley
* https://github.com/twpayne/go-xmlstruct

And other [awesome XML utilities](https://github.com/avelino/awesome-go#xml).

Expand Down Expand Up @@ -144,6 +146,8 @@ Usage of zek:
-F skip formatting
-P string
if set, write out struct within a package with the given name
-S int
read at most this many tags, approximately (0=unlimited)
-c emit more compact struct (noop, as this is the default since 0.1.7)
-d debug output
-e add comments with example
Expand Down
9 changes: 8 additions & 1 deletion cmd/zek/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var (
debug = flag.Bool("d", false, "debug output")
createExampleProgram = flag.Bool("p", false, "write out an example program")
tagName = flag.String("t", "", "emit struct for tag matching this name")
notInlineStructs = flag.Bool("I", false, "do not inline children tags as anonymous structs")
skipFormatting = flag.Bool("F", false, "skip formatting")
strict = flag.Bool("s", false, "strict parsing and writing")
exampleMaxChars = flag.Int("x", 25, "max chars for example")
Expand All @@ -35,6 +36,7 @@ var (
outputFile = flag.String("o", "", "if set, write to output file, not stdout")
packageName = flag.String("P", "", "if set, write out struct within a package with the given name")
fixedBanner = flag.Bool("B", false, "use a fixed banner string (e.g. for CI)")
readAtMost = flag.Int64("S", 0, "read at most this many tags, approximately (0=unlimited)")
)

func main() {
Expand Down Expand Up @@ -73,7 +75,11 @@ func main() {
}
reader = io.MultiReader(rs...)
}
if _, err := root.ReadFrom(reader); err != nil {
opts := zek.ReadOpts{
MaxExamples: *maxExamples,
MaxTokens: *readAtMost,
}
if _, err := root.ReadFrom(reader, &opts); err != nil {
log.Fatal(err)
}
// Move root, if we have a tagName. Ignore unknown names.
Expand All @@ -99,6 +105,7 @@ func main() {
sw.Strict = *strict
sw.ExampleMaxChars = *exampleMaxChars
sw.Compact = !*nonCompact
sw.InlineStructs = !*notInlineStructs
sw.UniqueExamples = *uniqueExamples
sw.OmitEmptyText = *omitEmptyText
if *fixedBanner {
Expand Down
3 changes: 3 additions & 0 deletions docs/zek.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ at https://www.onlinetool.io/xmltogo/.
-s
: Strict parsing.

-S
: raed at most this many tokens, approximately (0=unlimited)

-t
: Emit struct for tag matching this name.

Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module github.com/miku/zek

go 1.12
go 1.17

require (
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 // indirect
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
golang.org/x/text v0.3.7 // indirect
github.com/sethgrid/pester v1.2.0
golang.org/x/net v0.19.0
)

require golang.org/x/text v0.14.0 // indirect
47 changes: 36 additions & 11 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0 h1:X9XMOYjxEfAYSy3xK1DzO5dMkkWhs9E9UCcS1IERx2k=
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0/go.mod h1:Ad7IjTpvzZO8Fl0vh9AzQ+j/jYZfyp2diGwI8m5q+ns=
github.com/sethgrid/pester v1.2.0 h1:adC9RS29rRUef3rIKWPOuP1Jm3/MmB6ke+OhE5giENI=
github.com/sethgrid/pester v1.2.0/go.mod h1:hEUINb4RqvDxtoCaU0BNT/HV4ig5kfgOasrf1xcvr0A=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
22 changes: 17 additions & 5 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,16 @@ type Node struct {
childFreqs map[xml.Name]int // Count child tag occurrences, used temporarily.
}

// ReadOpts groups options for parsing.
type ReadOpts struct {
MaxExamples int
MaxTokens int64
}

// readNode reads XML from a reader and returns a parsed node. If node is
// given, it is reused, allowing for multiple passes (e.g. from multiple
// files). XXX: maxExamples should be factored out into options.
func readNode(r io.Reader, root *Node, maxExamples int) (node *Node, n int64, err error) {
func readNode(r io.Reader, root *Node, opts *ReadOpts) (node *Node, n int64, err error) {
var (
cw = countwriter{}
dec = xml.NewDecoder(io.TeeReader(r, &cw))
Expand All @@ -60,6 +66,8 @@ func readNode(r io.Reader, root *Node, maxExamples int) (node *Node, n int64, er
}
stack := Stack{}
stack.Put(root)
var i int64
OUTER:
for {
token, err := dec.Token()
if err == io.EOF {
Expand All @@ -68,6 +76,7 @@ func readNode(r io.Reader, root *Node, maxExamples int) (node *Node, n int64, er
if err != nil {
return root, cw.n, err
}
i++
switch t := token.(type) {
case xml.StartElement:
parent := stack.Peek().(*Node)
Expand All @@ -76,13 +85,16 @@ func readNode(r io.Reader, root *Node, maxExamples int) (node *Node, n int64, er
case xml.EndElement:
n := stack.Pop().(*Node)
n.End()
if opts.MaxTokens > 0 && i > opts.MaxTokens {
break OUTER
}
case xml.CharData:
v := strings.TrimSpace(string(t))
if v == "" {
break
}
n := stack.Peek().(*Node)
if len(n.Examples) < maxExamples {
if len(n.Examples) < opts.MaxExamples {
// XXX: sample better, e.g. reservoir dictionary.
n.Examples = append(n.Examples, v)
}
Expand All @@ -92,9 +104,9 @@ func readNode(r io.Reader, root *Node, maxExamples int) (node *Node, n int64, er
return root, cw.n, nil
}

// ReadFrom reads XML from a reader.
func (node *Node) ReadFrom(r io.Reader) (int64, error) {
nn, n, err := readNode(r, nil, node.MaxExamples)
// ReadFrom reads XML from a reader. TODO: pass read options.
func (node *Node) ReadFrom(r io.Reader, opts *ReadOpts) (int64, error) {
nn, n, err := readNode(r, nil, opts)
if err != nil {
return n, err
}
Expand Down
8 changes: 4 additions & 4 deletions node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ func TestNodeReadFrom(t *testing.T) {
for _, c := range cases {
r := strings.NewReader(c.input)
node := new(Node)
_, err := node.ReadFrom(r)
_, err := node.ReadFrom(r, &ReadOpts{MaxExamples: 10})
if err != c.err {
t.Errorf("got %v, want %v", err, c.err)
}
Expand Down Expand Up @@ -462,7 +462,7 @@ func TestHeight(t *testing.T) {
for _, c := range cases {
r := strings.NewReader(c.input)
node := new(Node)
_, err := node.ReadFrom(r)
_, err := node.ReadFrom(r, &ReadOpts{MaxExamples: 10})
if err != nil {
t.Errorf("failed to parse tree: %s", err)
}
Expand All @@ -475,7 +475,7 @@ func TestHeight(t *testing.T) {
func TestByName(t *testing.T) {
r := strings.NewReader(`<a><b><c></c></b></a>`)
root := new(Node)
if _, err := root.ReadFrom(r); err != nil {
if _, err := root.ReadFrom(r, &ReadOpts{MaxExamples: 10}); err != nil {
t.Errorf("got %v, want nil", err)
}

Expand Down Expand Up @@ -892,7 +892,7 @@ func TestNodeReadFromAll(t *testing.T) {
}

node := new(Node)
_, err := node.ReadFrom(io.MultiReader(readers...))
_, err := node.ReadFrom(io.MultiReader(readers...), &ReadOpts{MaxExamples: 10})
if err != c.err {
t.Errorf("got %v, want %v", err, c.err)
}
Expand Down
2 changes: 1 addition & 1 deletion packaging/deb/control.amd64
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: zek
Version: 0.1.16
Version: 0.1.21
Section: utils
Priority: optional
Architecture: amd64
Expand Down
2 changes: 1 addition & 1 deletion packaging/deb/control.any
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: zek
Version: 0.1.16
Version: 0.1.21
Section: utils
Priority: optional
Architecture: any
Expand Down
2 changes: 1 addition & 1 deletion packaging/deb/zek/DEBIAN/control
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: zek
Version: 0.1.16
Version: 0.1.21
Section: utils
Priority: optional
Architecture: amd64
Expand Down
2 changes: 1 addition & 1 deletion packaging/rpm/zek.spec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Summary: Generate a Go struct from an XML document.
Name: zek
Version: 0.1.16
Version: 0.1.21
Release: 0
License: GPL
BuildArch: x86_64
Expand Down
Loading