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

Cannot use non-namespaced (but included) types in schema #121

Open
johnnybubonic opened this issue Aug 26, 2020 · 4 comments
Open

Cannot use non-namespaced (but included) types in schema #121

johnnybubonic opened this issue Aug 26, 2020 · 4 comments

Comments

@johnnybubonic
Copy link

johnnybubonic commented Aug 26, 2020

So let's say I have a schema that includes a (non-namespaced/generic) additional schema which finally includes an another generic/non-NS schema.

When I try to use those schemas, e.g. python's LXML handles it fine, no complaints. xmllint, same thing. but when i run go generate with //go:generate xsdgen -ns https://aif-ng.io/ -pkg config /opt/dev/xml/schema/projects/aif.xsd, I get the following error: complexType storage: could not find type "t_linux_luks" in namespace https://aif-ng.io/ for element luks gen.go:3: running "xsdgen": exit status 1

Note that it isn't always t_linux_luks; it entirely depends on which element it gets to first. My above example is in reference to me getting errors regarding a missing t_std_nonempty (hence me linking to that specific schema include). Run it a couple times, you'll see different errors.

If you want a sample doc, you can find one here. You can clone the XML schemas and types etc. from here[0].

For reference, this is what I have in my gen.go:

package config

//go:generate xsdgen -ns https://aif-ng.io/ -pkg config /opt/dev/xml/schema/projects/aif.xsd

(Obviously your /opt/dev/xml would be the path to the XML repo I linked.)

[0] Has there been a feature request to support remote schemas yet? You can get it from an XML document pretty easily if it has an xsi:schemaLocation (it's the second value), otherwise it'd be great if xsdgen's positional arg would let you specify an HTTP resource.

@StabbyCutyou
Copy link

StabbyCutyou commented Oct 22, 2020

I'm running into this exact same problem.

I suspect the reason the error is not idempotent w/r/t which type isn't found, is because of how iterating maps in go is non-deterministic, and there is a lot of map iteration going on.

I think problem is here: https://github.com/droyo/go-xml/blob/master/xsd/parse.go#L148

The empty value of tns means that each time we don't find this, we set the key of "" to equal the latest schema root element we've iterated over, and so what happens is that you only get the last one under the "" key.

Then later when we go to resolve the global-list of types against the doc it thinks the namespace is for, it's only a matter of time before you hit something from one of the ones we parsed but accidentally rejected.

I've been attempting to hack around this to find a solution, and I've found something unique about each root that i can use instead of the namespace value we are trying to find, but that hasn't solved it yet, so I might still be missing something.

@StabbyCutyou
Copy link

StabbyCutyou commented Oct 22, 2020

ok, yea that solves it.

So, I don't think this is the best way to go about it, but if you alter the code in Parse, where it ranges over the schema object to do this:

		tns := root.Attr("", "targetNamespace")
		key := tns
		if key == "" {
			key = root.String()
		}

then have it set parsed[key] = s

then after pre-collecting types, the next range over schema, make a similar change:

		tns := root.Attr("", "targetNamespace")
		if tns == "" {
			tns = root.String()
		}
		s := parsed[tns]

That resolves it - assuming you don't have two documents that are completely identical. Also, this is definitely not very memory efficient but i'd wager that is less pressing than not being able to resolve types.

Unfortunately for me, I then run into this issue #117 lol

@droyo
Copy link
Owner

droyo commented Nov 1, 2020

That's pretty clever, using the whole document as an identifier. If you want to reduce the memory usage you could use a checksum of the document as a key.

Here's what the XSD spec has to say about empty target namespaces: https://www.w3.org/TR/xmlschema-0/#UndeclaredTNS

Element declarations from a schema with no target namespace validate unqualified elements in the instance document.

@StabbyCutyou , with the fix you proposed, what does the generated code look like? Does the XML document get used as a namespace? If so, I think the xsd and xsdgen packages would have to be changed to respect empty namespaces.

What's not clear to me from the spec, is how multiple schema with an empty target namespace should be handled. Should they be merged? What do more mature tools do?

I suspect what we'll end up doing is handling undeclared target namespace specially, and updating the command line tool to allow users to select a "primary" schema file. Currently you can only select a schema by namespace, which doesn't work when they don't have namespaces.

@johnnybubonic , regarding remote schema, see #35

@johnnybubonic
Copy link
Author

@droyo Thanks! Subscribed and will monitor there for possible fixes/merge in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants