Is it allowed to have multiple elements with same name in XSD?

14,444

The client says it's valid XSD. But I don't know if it is.

It's not valid XSD, and thus not conforming XSD, but not for the reasons you're asking about.

The complex type given for the local element Invoice in CreditInvoice.xsd is not valid: it has an xsd:element element as a child of xsd:complexType. I assume this is a typo resulting from whatever you did to cut the example down to a manageable size. If the declaration for CreditNo is moved into the xsd:sequence element, the schema document becomes valid, and the schema defined by the three schema documents you give becomes a conforming schema.

On the question of having local elements with the same name as top-level / global elements, your client is without question correct. It's legal, it's intended to be legal, it's an important part of the design of XSD. (@Augusto may be right that it can be confusing; designers should certainly be careful in their use of this feature. But it's definitely conformant.)

How should it (Main.xsd) know which Invoice element it should reference to? I see the same error using another tool.

You say "same error", but you haven't described an error message. Perhaps you mean that another tool also seems to take the <xs:element ref="Invoice" /> in Main.xsd as a reference to the Invoice defined in CreditInvoice.xsd and not as a reference to the Invoice defined in Invoice.xsd.

Any reference to an element, like the <xs:element ref="Invoice" /> in Main.xsd, is a reference to a top-level (aka global) element with a matching name. In a conforming schema there will always be at most one such element. So when the schema is constructed from the declarations in the various schema documents in your example, any conforming processor will know that the Invoice element which can appear as a child of Invoices is the top-level Invoice element declared in Invoice.xsd. It cannot be the Invoice element declared in CreditInvoice.xsd, because that element is local to the complex type of the CreditInvoice element. Like any local element, it can be used where declared and cannot be used elsewhere.

If you are correct in saying that the tools you mention treat the element reference in Main.xsd as a reference to the Invoice declared local to CreditInvoice in CreditInvoice.xsd, then you have just identified a bug in those tools. If you care about the tools and have any goodwill to the vendors, you should report the issue so they can fix it.

However if I open Main.xsd using Stylus Studio XML Professional it looks OK.

Can anyone tell me which behaviour is correct?

The spec can tell you; reliable books can tell you; reliable tools can tell you (with a lot less effort than reading it up in the spec).

Share:
14,444
Admin
Author by

Admin

Updated on June 14, 2022

Comments

  • Admin
    Admin almost 2 years

    I am having a discussion with a client whether it's allowed to have multiple elements in an XSD with the same name. Let me try and explain.

    CreditInvoice.xsd (contains an Invoice element inside CreditInvoice element)

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
      <xs:element name="CreditInvoice">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Invoice" minOccurs="0" maxOccurs="unbounded">
              <xs:complexType>
                <xs:element name="CreditNo" type="xs:string" />
                <xs:sequence>
                  <xs:element name="InvoiceDate" type="xs:date" />
                  <xs:element name="InvoiceNo" type="xs:string" />
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    Invoice.xsd (contains a root Invoice element)

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
      <xs:element name="Invoice">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="InvoiceDate" type="xs:date" />
            <xs:element name="InvoiceNo" type="xs:string" />
            <xs:element name="InvoiceReceiver" type="xs:string" />
            <xs:element name="DueDate" type="xs:date" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    Main.xsd (Main XSD document that includes the other XSD documents.)

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
      <xs:include schemaLocation="CreditInvoice.xsd"/>
      <xs:include schemaLocation="Invoice.xsd"/>
    
      <xs:element name="Invoices">
        <xs:complexType>
          <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
              <xs:element ref="CreditInvoice" />
              <xs:element ref="Invoice" />
            </xs:choice>
          </xs:sequence>      
        </xs:complexType>
      </xs:element>
    
    </xs:schema>
    

    When I open Main.xsd in for example CAM Template Editor (http://www.cameditor.org) the element ref to Invoice in Main.xsd uses the Invoice element defined in CreditInvoice.xsd instead of the element defined in Invoice.xsd which the client is trying to achieve.

    If I change the order of the include elements to include Invoice.xsd before CreditInvoice.xsd it works OK.

    The client says it's valid XSD. But I don't know if it is. How should it (Main.xsd) know which Invoice element it should reference to? I see the same error using another tool.

    However if I open Main.xsd using Stylus Studio XML Professional it looks OK.

    Can anyone tell me which behaviour is correct?