ghord
ghord

Reputation: 13797

Extend existing XSD schema with custom attribute

I need to add some custom attribute to xml file that is validated by existing, already defined schema.

Given existing xml element:

<existingElement attr1="1" attr2="2" />

Validated with existing xsd schema, I want to make it possible to add custom attribute to this element without breaking the schema validation in the process:

<existingElement attr1="1" attr2="2" xmlns:my="http://example.com/node" my:id="myNodeId" />

I cannot modify the original schema file, and it does have anyAttribute element

What approach should I take?

I've tried to add another xsd file:

<xs:schema 
    targetNamespace="http://example.com/node"
    attributeFormDefault="qualified"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:attribute name="id" type="xs:string" />
</xs:schema>

But I keep getting Attribute 'http://example.com/node:id' was not declared.

I'm validating in .NET using XmlSchemaSet with both old and new schemas added.

Upvotes: 0

Views: 1076

Answers (2)

Alexander Petrov
Alexander Petrov

Reputation: 14231

test.xml

<?xml version="1.0" encoding="utf-8"?>
<existingElement attr1="1" attr2="2" xmlns:my="http://example.com/node" my:id="myNodeId" />

test1.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="existingElement">
    <xs:complexType>
      <xs:attribute name="attr1" type="xs:unsignedByte" use="required" />
      <xs:attribute name="attr2" type="xs:unsignedByte" use="required" />
      <xs:anyAttribute />
    </xs:complexType>
  </xs:element>
</xs:schema>

test2.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://example.com/node"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:attribute name="id" type="xs:string" />
</xs:schema>

C# code

var schemaSet = new XmlSchemaSet();
schemaSet.Add("", "test1.xsd");
schemaSet.Add("http://example.com/node", "test2.xsd");
schemaSet.Compile();

var xml = XDocument.Load("test.xml");
xml.Validate(schemaSet, (o, e) =>
{
    Console.WriteLine(e.Severity + ": " + e.Message);
});

It works. There are no validation errors.

Upvotes: 0

Michael Kay
Michael Kay

Reputation: 163262

At some level, you MUST modify the existing schema, because you are trying to create an instance document that violates one of its constraints.

If the original schema defines the structure using a named complex type, then you can modify the existing schema without textual change to the text of the schema document using one of two mechanisms: xs:redefines, or defining a new complex type using "derivation by extension". Both of these modify the schema without modifying the schema document: so it depends a bit what you mean by your requirement of not modifying the schema. Note that if you use "derivation by extension" then your instance will have to flag that it uses the extension by including an xsi:type attribute that names the extended complex type.

If your concern about modifying the schema is about forking the XSD source definition, then another way to define your modified schema is as an XSLT transformation applied to the original. This is actually very similar to xs:redefines, except that you can make any changes you like, whereas xs:redefined constrains what you can change.

One the other hand, if your concern is to ensure that documents conforming to the new schema are still compatible with applications using the old schema, then all these mechanisms fail: in all cases, you are creating documents that don't conform to the existing schema and that therefore have potential to break applications that rely on the documents being valid against that schema.

Upvotes: 1

Related Questions