Bhagwat Gurle Bhagwat Gurle -4 years ago 127
Java Question

Making one element optional/mandatory based on another element value using xsd:assert

I am trying to apply validation of mandatory and optional on one element of xml which is depending upon value of other element.

Below is XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">

<xs:element name="root" type="root"></xs:element>

<xs:complexType name="root">
<xs:sequence>
<xs:element name="P1Message"
type="p1Message">
</xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="p1Message">
<xs:sequence>
<xs:element name="Hdr" type="hdr"></xs:element>
<xs:element name="Inf" type="inf"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="hdr">
<xs:sequence>
<xs:element name="I1Agt" type="i1Agt"></xs:element>
<xs:element name="SequenceNum" type="xs:string"></xs:element>
<xs:element name="SessionNum" type="xs:string"></xs:element>
<xs:element name="MsgTyp" type="xs:string"></xs:element>
<xs:element name="IntComment" type="xs:string"></xs:element>
</xs:sequence>
<xs:assert test="LclInstrm or not(MsgTyp = '103')"/>
</xs:complexType>

<xs:complexType name="i1Agt">
<xs:sequence>
<xs:element name="FinInstnId" type="finInstnId"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="finInstnId">
<xs:sequence>
<xs:element name="B1" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="inf">
<xs:sequence>
<xs:element name="PmtTpInf" type="pmtTpInf"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="pmtTpInf">
<xs:sequence>
<xs:element name="LclInstrm" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
<xs:element name="Svc" type="svc"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="svc">
<xs:sequence>
<xs:element name="Cd" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>


Below is XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
<P1Message>
<Hdr>
<I1Agt>
<FinInstnId>
<B1>str1234</B1>
</FinInstnId>
</I1Agt>
<SequenceNum>str1234</SequenceNum>
<SessionNum>str1234</SessionNum>
<MsgTyp>123</MsgTyp>
<IntComment>str1234</IntComment>
</Hdr>
<Inf>
<PmtTpInf>
<LclInstrm>str1234</LclInstrm>
<Svc>
<Cd>str1234</Cd>
</Svc>
</PmtTpInf>
</Inf>
</P1Message>
</root>


I want to make 'LclInstrm' element mandatory when value of 'MsgTyp' is 103.

When I am trying to validate above XML with XSD in Java I am getting below error:

message.xml is not valid because cvc-assertion.3.13.4.1: Assertion evaluation ('LclInstrm or not(MsgTyp = '103')') for element 'Hdr' with type 'hdr' did not succeed.


could anyone please help me with same?

Please let me know if you require more details.

Thank you!

Answer Source

Your XPath in the assertion is off because it's assuming that LclInstrm and MsgTyp are siblings when they're not.

Your assertion will have to go on a common ancestor (P1Message) and reference the correct relative paths to each element.

So, your assertion on P1Message would be:

<xs:assert test="Inf/PmtTpInf/LclInstrm or not(Hdr/MsgTyp = '103')"/>

Another working example of how to use an assertion to conditionally require an element based upon the value of another element can be found here: Require XML element in XSD when another element has certain value?

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download