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

Referenced node has no explicit xmlns namespace when marshalling

Open makon opened this issue 5 years ago • 4 comments

Hi, I am trying to include the external xmldsig schema into my schema and to generate the structs. This steps works and this is great! In the next step I use xmlsec1 to sign the marshalled XML but then it complains that it can't find the Signature node.

Error: failed to find default node with name="Signature"

It seems that xmlsec1 expects that the marshalled XML contains a Signaute node with its explicit xmlns namespace/

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">

When I am marshalling the XML I get a Signature node without its namespace but all its child nodes contain it. Is it somehow possible to achieve that the Signature node also has its namespace explicitly when marshalled?

Result:

<MetaDataType>
  <Signature>
    <SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <CanonicalizationMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference xmlns="http://www.w3.org/2000/09/xmldsig#">
        <DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue xmlns="http://www.w3.org/2000/09/xmldsig#"/>
      </Reference>
    </SignedInfo>
    <SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#"/>
  </Signature>
</MetaDataType>

Schema:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
           elementFormDefault="qualified">
    <xs:import namespace="http://www.w3.org/2000/09/xmldsig#"
               schemaLocation="xmldsig-core-schema.xsd" />

    <xs:element name="MetaData" type="MetaDataType" />
    <xs:complexType name="MetaDataType">
        <xs:sequence>
            <xs:element ref="ds:Signature"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Generated code:

type MetaDataType struct {
	Signature *SignatureType `xml:" Signature"`
}

type SignatureType struct {
	SignedInfo     *SignedInfoType     `xml:"http://www.w3.org/2000/09/xmldsig# SignedInfo"`
	SignatureValue *SignatureValueType `xml:"http://www.w3.org/2000/09/xmldsig# SignatureValue"`
	KeyInfo        *KeyInfoType        `xml:"http://www.w3.org/2000/09/xmldsig# KeyInfo,omitempty"`
	Object         []ObjectType        `xml:"http://www.w3.org/2000/09/xmldsig# Object,omitempty"`
	Id             string              `xml:"Id,attr,omitempty"`
}

makon avatar Apr 09 '19 09:04 makon

Thanks for the report.

The problem appears to be that the root element, regardless of what it is, doesn't get a namespace. This could be fixed in the code generation by adding an XMLName field. In your example, we'd generate something like

type SignatureType struct {
	XMLName        xml.Name            `xml:"http://www.w3.org/2000/09/xmldsig# Signature"`
	SignedInfo     *SignedInfoType     `xml:"http://www.w3.org/2000/09/xmldsig# SignedInfo"`
	SignatureValue *SignatureValueType `xml:"http://www.w3.org/2000/09/xmldsig# SignatureValue"`
	KeyInfo        *KeyInfoType        `xml:"http://www.w3.org/2000/09/xmldsig# KeyInfo,omitempty"`
	Object         []ObjectType        `xml:"http://www.w3.org/2000/09/xmldsig# Object,omitempty"`
	Id             string              `xml:"Id,attr,omitempty"`
}

droyo avatar Apr 10 '19 20:04 droyo

Actually, looking at this closer, the fact that the Signature field in MetaDataType does not have a namespace seems like a bug.

I recall a previous issue where the code failed to preserve namespaces when importing types across namespace boundaries (as your schema does), but I thought I fixed that. The fact that this schema does not declare a targetNamespace may be relevant -- can you try adding a targetNamespace declaration (the value doesn't matter) to the schema element and try codegen again?

droyo avatar Apr 10 '19 20:04 droyo

Thanks for the fast respone. So I changed the schema to

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
           xmlns:ex="urn:example"
           targetNamespace="urn:example"
           elementFormDefault="qualified">
    <xs:import namespace="http://www.w3.org/2000/09/xmldsig#"
               schemaLocation="xmldsig-core-schema.xsd" />

    <xs:element name="MetaData" type="ex:MetaDataType" />
    <xs:complexType name="MetaDataType">
        <xs:sequence>
            <xs:element ref="ds:Signature"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

and adjusted the namespace flag to

xsdgen -pkg=main -o=xsd/test.go -ns "urn:example" xsd/test.xsd xsd/xmldsig-core-schema.xsd

and in this case it seems to use the target namespace but in my case I would expect that Signautre would have the namespace of xmldsig?

type MetaDataType struct {
	Signature *SignatureType `xml:"urn:example Signature"`
}

type SignatureType struct {
	SignedInfo     *SignedInfoType     `xml:"http://www.w3.org/2000/09/xmldsig# SignedInfo"`
	SignatureValue *SignatureValueType `xml:"http://www.w3.org/2000/09/xmldsig# SignatureValue"`
	KeyInfo        *KeyInfoType        `xml:"http://www.w3.org/2000/09/xmldsig# KeyInfo,omitempty"`
	Object         []ObjectType        `xml:"http://www.w3.org/2000/09/xmldsig# Object,omitempty"`
	Id             string              `xml:"Id,attr,omitempty"`
}

the xml output is now

<Signature xmlns="urn:example">

Did I do something wrong? I am not sure if this was what you thought about. I am not really an expert in XSD schemas... sorry.

What I forgot to mention is that I am using the omitempty-structs branch but I merged the latest master into it. I also tried it with the master with the same result.

makon avatar Apr 11 '19 15:04 makon

It looks like setting the targetNamespace did not fix the issue and this is a variation of #65 ; elements in another namespace mistakenly get labelled with the targetNamespace of the schema containing the reference.

droyo avatar Apr 11 '19 17:04 droyo