go-xml icon indicating copy to clipboard operation
go-xml copied to clipboard

xsd: `ref`s are parsed with wrong namespace and type

Open WKBae opened this issue 8 months ago • 0 comments

When ref is used in the xsd definition, its type and namespace are parsed incorrectly.

attributeDefaultType adds default type="xsd:anySimpleType" to ref attributes which does(and should) not have type attribute itself.

3.2 If ref is present, then all of <simpleType>, form and type must be absent. #

deref copies source attributes(real.StartElement.Attr) without considering the namespace of name attribute. As XmlSchema spec states name is NCName (not QName), references across namespaces cannot be Normalized in XML level while conforming the spec.

I suggest:

  1. Add not(hasAttr("", "ref")) check in attributeDefaultType
  2. Move/Integrate flattenRef to Parse instead of Normalize (at least for refs to external namespace)

Reproducible code

a.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com/a" targetNamespace="http://example.com/a">
  <xsd:simpleType name="ST_Text">
    <xsd:restriction base="xsd:string"/>
  </xsd:simpleType>
  <xsd:attribute name="value" type="ST_Text"/>
</xsd:schema>

b.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com/b" xmlns:a="http://example.com/a" targetNamespace="http://example.com/b">
  <xsd:import namespace="http://example.com/a" schemaLocation="a.xsd"/>
  <xsd:complexType name="CT_Root">
    <xsd:attribute ref="a:value"/>
  </xsd:complexType>
</xsd:schema>

main.go:

package main

import (
	_ "embed"
	"encoding/xml"
	"fmt"

	"aqwari.net/xml/xsd"
)

//go:embed a.xsd
var a []byte

//go:embed b.xsd
var b []byte

func main() {
	schema, err := xsd.Parse(a, b)
	if err != nil {
		panic(err)
	}
	for _, s := range schema {
		if s.TargetNS == "http://example.com/b" {
			attrs := s.FindType(xml.Name{Space: "http://example.com/b", Local: "CT_Root"}).(*xsd.ComplexType).Attributes
			for _, attr := range attrs {
				fmt.Printf("%+v %T\n", attr.Name, attr.Type)
			}
		}
	}
}

Expected: {Space:http://example.com/a Local:value} *xsd.SimpleType (a:value with type a:ST_Text having Base: String) Actual: {Space:http://example.com/b Local:value} xsd.Builtin ((b:)value with type AnySimpleType)

WKBae avatar Mar 23 '25 19:03 WKBae