2

I have the following XML:

<root>
  <someNode>
    <someChild attr="val" />
  </someNode>

  <otherNode>
    <otherChild>
      <otherSubChild />
    </otherChild>
  </otherNode>
</root>

A valid XML Schema for this will be very easy. Now the problem is, my program must support a special element which is evaluated when parsing the file, and leads to conditional substitution of elements.

Example:

    <root>
      <someNode>
        <if environment="DEV">
          <someChild attr="val" />
        </if>
        <if environment="PROD">
          <someChild attr="otherVal" />
        </if>
      </someNode>

      <otherNode>
        <otherChild>
          <if environment="DEV">
            <otherSubChild />
          </if>
        </otherChild>
      </otherNode>
    </root>

I think you get the idea. The thing is, the if element is allowed to appear everywhere in the XML, but at the same time allowed to include any element which is allowed for the element it is put in.

How would I define this in a good way? Currently I am having about 90 types/elements in my XML schema, and it would be really cumbersome to manually edit every single type/element to allow an if element which allows the correct child elements.

Is it possible to make a schema which allows the if element as I described above?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
user826955
  • 3,137
  • 2
  • 30
  • 71

3 Answers3

1

So, you've specified a hierarchy of content models that say specifically what elements can appear in what other elements, in what quantities and possibly in what orders as well. And now you want to add, By the way, an if element can wrap any existing element anywhere?

You can't do that in XSD. You can't counter all of your specific constraints globally in that manner without modifying those specific instructions, or without having made provisions for such a possibility a priori. (For example, had you defined an element substitution group, that could appear multiple places throughout your document, you could easily add a new member to the group.)

There's a way to say that any element can appear at a given spot within a content model (xs:any), but there is no way to say that a given element can appear anywhere in all content models. In XSD 1.1, there is a new mechanism to allow open content in content models, but that too allows for forward looking provisions, not retroactive global adjustments.

One suggestion might be to write a simple XSLT transformation between the with-if and without-if forms of your XML and separately validate those documents.

Another approach would be to express your condition as an attribute that would appear on any element, rather than an element that can wrap any other element. This would still require updates to your XSD, but the updates would be easier to make while preserving your existing content models.

Community
  • 1
  • 1
kjhughes
  • 106,133
  • 27
  • 181
  • 240
1

Although this answer comes late, I thought I would contribute for completeness and future readers.

The if attribute in kjhughes' answer is the one I would recommend if validation rules are important. OTOH, the OP didn't specify whether the <if> must be validated, just that a generic, non-invasive, XML schema-based solution is seeked.

If no validation of the <if> is needed, processing instructions (PI) may offer what the OP needs: without editing the schema at all, they can be used to define alternative content depending on the target environment (DEV/PROD).

That's exactly what PI were designed for: they don't add content to xml data (or at least, we're not supposed to put content in them); they are not validated; they add meaning only to "processors" of the data. Applications that parse the XML do not need to understand them (depending on what you do with them, of course).

<root>
  <someNode>
    <?environment DEV?>
    <someChild attr="val" />

    <?environment PROD?>
    <someChild attr="otherVal" />
  </someNode>

  <otherNode>
    <otherChild>
      <?environment DEV?>
      <otherSubChild />
    </otherChild>
  </otherNode>
</root>

Caveat: Depending on the schema, it might be invalid to have 2 <someChild> inside <someNode>, in which case this document would require pre-processing before validation, but this is the same with the if attribute option.

Ben
  • 17
  • 6
  • 2
    Is it not the only purpose of a schema to validate XML [(definition)](https://www.w3.org/standards/xml/schema)? Therefore, OP indeed needs to validate his XML. – stackprotector Apr 16 '20 at 08:07
  • @Thomas The OP definitely needs to validate his XML (otherwise why bother with a schema), but not necessarily the fact that there are alternative environments (the ``). – Ben Apr 17 '20 at 15:40
0

Maybe you could try to define a basic complexType for the <if> element and its attributes and then declare <someChild> and <otherChild> as extensions of this type.

colibrisson
  • 161
  • 1
  • 11