How to allow element to appear 0, or 2 or more times

Here should go questions about transforming XML with XSLT and FOP.
mlcook
Posts: 67
Joined: Thu Jan 24, 2008 4:52 pm

How to allow element to appear 0, or 2 or more times

Post by mlcook »

I have a working schema for data that we use, and want to expand it to do more checking on the XML elements.

We have a particular data element, say <FM>, that does not have to appear in our data, but if it does, it must appear at least twice, and possibly more.

That is, I want to detect a singular occurance of <FM>.

There are other sibling elements along with <FM>.

Can this be done, and can it be done with the schema itself, or with uniqueness constraints, or???

I'm using Oxygen 9.1.

Thanks, Mike
sorin_ristache
Posts: 4141
Joined: Fri Mar 28, 2003 2:12 pm

Re: How to allow element to appear 0, or 2 or more times

Post by sorin_ristache »

Hello,

What is the language of your schema (XML Schema, RELAX NG, etc)? Did you try with a Schematron constraint in the definition of the content model where the FM element must appear at least twice? It should be only a Schematron rule with one assertion: the FM child element has zero appearances or at least two appearances.


Regards,
Sorin
mlcook
Posts: 67
Joined: Thu Jan 24, 2008 4:52 pm

Re: How to allow element to appear 0, or 2 or more times

Post by mlcook »

I'm using XML Schema. (In Oxygen, how do I tell which version of XML Schema I'm using, and how do I use schema version 1.1?)

I think I might want something like:

Code: Select all

    <xs:complexType name="BEType">
<xs:complexContent>
<xs:extension base="t:RSEType">
<xs:sequence>
<xs:element name="a" type="t:AType"/>
<xs:element name="b" type="t:BType"/>
<xs:element name="c" type="t:CType"/>

<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="t:RBElement"/>
<xs:choice>
<xs:element ref="t:RBFMElement" minOccurs="2" maxOccurs="unbounded"/>
<xs:sequence/>
</xs:choice>
</xs:choice>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
That is, there are some required initial elements.
Then there are several RBElements. Among the RBElements, I'd like to have some RBFMElements, but those must either be non-existent, or occur 2 or more times (together is fine).
After the RBFMElements, there would be more RBElements.
(The RBFMElements are preceeded and followed by RBElements.)

However, during validation the first Choice does not allow more than 1 RBElement in my XML file, and does not get to the RBFMElements.

Someone has suggested <xs:assert test="count(RBFMElement) != 1"/>
but that is only available in Schema 1.1 which I don't think I'm using, and don't know where in the schema that line would go.

A solution with Schema 1.0 would be preferred.

Thanks for any light on this.
sorin_ristache
Posts: 4141
Joined: Fri Mar 28, 2003 2:12 pm

Re: How to allow element to appear 0, or 2 or more times

Post by sorin_ristache »

Hello,

In Oxygen the default validator for XML Schema is Xerces which is not XML Schema 1.1 aware. You can validate an XML Schema 1.1 schema with Saxon SA for which Oxygen has a built-in validation configuration. After you place the Saxon 9 SA jar file and license file in the folder [Oxygen-install-folder]/lib and restart Oxygen you validate an XML Schema 1.1 schema with the SaxonSA validator available on the toolbar External Validation.

If you choose a solution based on XML Schema 1.1 you do not have to specify the version number in the XSD file edited in Oxygen. Also you will not have elements and attributes of XML Schema 1.1 in the content completion popup. The line

Code: Select all

<xs:assert test="count(RBFMElement) != 1"/>
should go in the definition of the complex type:

Code: Select all

...
</xs:sequence>
</xs:extension>
</xs:complexContent>
<xs:assert test="count(RBFMElement) != 1"/>
</xs:complexType>
Regards,
Sorin
george
Site Admin
Posts: 2095
Joined: Thu Jan 09, 2003 2:58 pm

Re: How to allow element to appear 0, or 2 or more times

Post by george »

Hi,

You also have the options of having some embedded Schematron rules in your XML Schema to check exactly the same thing as the sample XML Schema 1.1 assertion (in fact the assertion feature in XML Schema 1.1 comes from Schematron). If you have problems with that let us know and we will post a sample.

The problem comes from the fact that you interleave the RBFMElement with the RBElement elements. If you decide on a specific order then you can write that easily in XML Schema.

Hope that helps,
George
George Cristian Bina
mlcook
Posts: 67
Joined: Thu Jan 24, 2008 4:52 pm

Re: How to allow element to appear 0, or 2 or more times

Post by mlcook »

I'm still not clear on why my schema above is failing.

I was hoping I was close to the example below from chapter 13 of Patricia Walmsley's book Definitive XML Schema.

Can't I intermix RBFMElements with the RBElements?

I'm not seeing the critical difference.

[Side note: We don't have access to Saxon SA, so that solution is out. If a Schematron rule with Schema 1.0 would work, I'd definitely need help with that. A Schema 1.0 without Schematron would be best, but I'm open to a Schematron solution if it isn't too complex.]

Thanks again,
Mike

Code: Select all

<xsd:complexType name="ProductType">
<xsd:sequence>
<xsd:element name="number" type="ProdNumType"/>
<xsd:element name="name" type="xsd:string"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="size" type="SizeType"/>
<xsd:element name="color" type="ColorType"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
sorin_ristache
Posts: 4141
Joined: Fri Mar 28, 2003 2:12 pm

Re: How to allow element to appear 0, or 2 or more times

Post by sorin_ristache »

mlcook wrote:Among the RBElements, I'd like to have some RBFMElements, but those must either be non-existent, or occur 2 or more times (together is fine).
Your XML Schema 1.0 schema is failing because this condition cannot be enforced with XML Schema 1.0. If you allow intermixing of RBElements and RBFMElements as in the following definition of BEType then you cannot enforce the condition of zero or at least two instances of RBFMElement. For this additional condition in XML Schema 1.0 you need a Schematron rule:

Code: Select all

<xs:complexType name="BEType">
<xs:complexContent>
<xs:annotation>
<xs:appinfo xmlns:sch="http://purl.oclc.org/dsdl/schematron">
<sch:ns uri="namespace-of-RBFMElement" prefix="t"/>
<sch:pattern name="Check number of RBFMElement.">
<sch:rule context="BE">
<sch:assert test="count(RBFMElement) != 1">Must be no RBFMElement or at least 2 RBFMElements!</sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
<xs:extension base="t:RSEType">
<xs:sequence>
<xs:element name="a" type="t:AType"/>
<xs:element name="b" type="t:BType"/>
<xs:element name="c" type="t:CType"/>

<xs:element ref="t:RBElement"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="t:RBElement"/>
<xs:element ref="t:RBFMElement"/>
</xs:choice>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
You must replace namespace-of-RBFMElement with the namespace of RBFMElement for which you used the prefix t.


Regards,
Sorin
mlcook
Posts: 67
Joined: Thu Jan 24, 2008 4:52 pm

Re: How to allow element to appear 0, or 2 or more times

Post by mlcook »

I've modified my schema to include the Schematron elements you suggested (modified by my namespace, etc.).

However, the Schematron assertion doesn't seem get tested.

I used the assertion (where your RBFMElement assertion was placed)
<sch:assert test="12 > 99"/>
which didn't fail as I thought it should. The document validated correctly.

I'm also using LIBXML for validation in Oxygen.

Is there some Oxygen preference that needs to be set for Schematron to work correctly?

Sorry to have so much trouble with this question.

-- Mike
mlcook
Posts: 67
Joined: Thu Jan 24, 2008 4:52 pm

Re: How to allow element to appear 0, or 2 or more times

Post by mlcook »

Got it!

I wasn't using the External Validation to get Schematron involved.

After viewing George's demo:
http://www.oxygenxml.com/demo/schematro ... atron.html
and then refining my schema, I got things to work.

Thanks a lot for the example above. Once I correctly converted it to my namespace, etc., things worked fine.

-- Mike
Post Reply