4

I have an XML that looks like this:

<Artifacts count="2">
  <Artifact>
    ...
  </Artifact>
  <Artifact>
    ...
  </Artifact>
 </Artifacts>

I am looking for a way to enforce that the number of Artifact elements contained in Artifacts shall be equal to the value of the "count" attribute by using an XSD schema.

Even though I found possible ways to achieve this by using the XSD 1.1 specification, I wonder if it is at all possible without it, i.e based on the XSD 1.0 specification.


Edit: I will try to provide a little more context to the question in order to be more precise.
The XML file will be provided as input to a C++ application. The problem is that the development environment enforces the usage of the Xerces v. 2.8.0 library for parsing. To my understanding this version does not support the XSD 1.1 standard.

Of course, I can add extra code in order to check for the correct number of occurrences of Artifact elements after the XSD validation. I was hoping that there would be a way to avoid the extra code segment and completely validate the input file based on the XSD alone.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
Vag
  • 305
  • 3
  • 11

2 Answers2

2

The correct term for the kind of constraint you'd like to model is assertion. No, assertions are not possible in XML Schema 1.0. The only validation languages that support assertions are XML Schema 1.1 (xs:assert) and Schematron (sch:assert and sch:report).

Other than that, you could write XPath expressions or XSLT stylesheets that test for the correct number of Artifact elements:

/Artifacts/@count = count(/Artifacts/Artifact)

The XML file will be provided as input to a C++ application. The problem is that the development environment enforces the usage of the Xerces v. 2.8.0 library for parsing. To my understanding this version does not support the XSD 1.1 standard.

My guess is that Xerces 2.8.0 (an outdated version that is no longer supported) does not conform to XSD 1.1, but the easiest way to find out is to simply test it. Include any xs:assert in a schema and see what happens.

Of course, I can add extra code in order to check for the correct number of occurrences of "Artifact" elements after the XSD validation. I was hoping that there would be a way to avoid the extra code segment and completely validate the input file based on the XSD alone.

No, with only XSD 1.0 you cannot avoid those extra lines of code.


EDIT What @kjhughes wrote in a comment should actually be part of the answer:

This is correct, and I would also challenge OP's design that requires an attribute that merely mirrors the number of child attributes.

From the point of view of XML design, if this attribute does nothing else than state how many Artifact elements there are, why did you include it in the first place? You should always be reluctant to store redundant and recoverable information. For instance, there is no need to store the position of child elements like so:

<root>
  <child n="1"/>
  <child n="2"/>
</root>

And your count attribute does something very similar.

Mathias Müller
  • 22,203
  • 13
  • 58
  • 75
  • Thank you for your reply. I was hoping that there would be a way to manipulate the schema to do my bidding but it seems that there is not. I will give it some more time to see if any crazy ideas come up from other users otherwise this answer is great and correct! Meanwhile I am creating the schema with this limitation in mind and I am looking at ways to incorporate XLST and XPath. – Vag Apr 01 '15 at 12:29
  • This is correct, and I would also challenge OP's design that requires an attribute that merely mirrors the number of child attributes. – kjhughes Apr 01 '15 at 14:32
  • @kjhughes Good point, I've tried to edit this into my answer - let me know if it still needs improvement. – Mathias Müller Apr 01 '15 at 14:41
  • I do agree that this is a bad design decision but unfortunately it is not my design to change. I am only trying to inform a schema on the given XML file. – Vag Apr 02 '15 at 06:14
1

I'll assume that count value is dynamic based on actual number of Artifact elements. One way (since I don't know what's your context) could be to modify the XSD with minOccurs and maxOccurs according with this value and then validate against the new schema...

<xsd:complexType name="Artifacts">
    <xsd:sequence>
      <xsd:element name="Artifact" minOccurs="COUNT_VALUE" maxOccurs="COUNT_VALUE" />      
    </xsd:sequence>   
</xsd:complexType>
exoddus
  • 2,230
  • 17
  • 27
  • The value of `minOccurs` must be 0 or a positive integer, "COUNT_VALUE" will not work. – Mathias Müller Apr 01 '15 at 11:40
  • you're right @Mathias about minOccurs! why setting maxOccurs as the same value as count attribute from parsed input xml, saving to new schema, and validate against that new one will not work? – exoddus Apr 01 '15 at 11:44
  • Yes, that would work, but it's a lot of manual labour, don't you think? Every time you'd like to validate a document, you have to change the schema. In my opinion, the point of schemas is _automatic_ validation, whithout requiring human intervention. – Mathias Müller Apr 01 '15 at 11:47
  • Sure! It's dreadful! Just was my first approach to solve a problem without knowing all the context. But once you write this process, it's also automatic (not optimum nor best solution of course). – exoddus Apr 01 '15 at 11:54
  • I see - that would indeed be an option, but then 1) each document has its own schema, which is a bit weird and 2) if you can modify an XSD document, why not just test for this condition with an XPath expression directly? – Mathias Müller Apr 01 '15 at 12:01
  • Thank you for your reply. Unfortunately editing the XSD to match the XML seems a little off, since I am trying to enforce a template to the user. Your suggestion however would produce the desired result! – Vag Apr 01 '15 at 12:31