My requirement is to have an XSD file which checks the elements based on attribute values. I was able to write XSD up to a point where I can restrict the attribute values of Application/@Type
. Can anyone help me to complete the XSD file where I can make some elements required based on the Application/@Type
attribute?
I want to make
PackageArg
required only whenApplication/@Type
is "Batch"Version
required only whenApplication/@Type
is "Service"Project
required only whenApplication/@Type
is Web" or "Service"
XML File
<Applications>
<Application Name="ConfigManagement" Type="Web">
<ProjectDirName>ConfigManagement</ProjectDirName>
<Project>Web.ConfigManagement.csproj</Project>
<OutputDirName>ConfigManagement</OutputDirName>
</Application>
<Application Name="Util" Type="Web">
<ProjectDirName>Web</ProjectDirName>
<Project>Web.csproj</Project>
<OutputDirName>Util</OutputDirName>
</Application>
<Application Name="ConfigService" Type="Service">
<ProjectDirName>WebServices\ConfigService</ProjectDirName>
<Project>ConfigService.csproj</Project>
<Version>2015\04</Version>
<OutputDirName>ConfigService</OutputDirName>
</Application>
<Application Name="DeliverEmail" Type="Batch">
<ProjectDirName>\Batch\DeliverEmail</ProjectDirName>
<PackageArg>Release</PackageArg>
<OutputDirName>Tidal\DeliverEmail</OutputDirName>
</Application>
</Applications>
XSD File
<xs:element name="Applications" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Application" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:all>
<xs:element type="xs:string" name="ProjectDirName"/>
<xs:element type="xs:string" name="Project" minOccurs="0"/>
<xs:element type="xs:string" name="Version" minOccurs="0"/>
<xs:element type="xs:string" name="PackageArg" minOccurs="0"/>
<xs:element type="xs:string" name="OutputDirName"/>
</xs:all>
<xs:attribute type="xs:string" name="Name" use="optional"/>
<xs:attribute name="Type" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Web"/>
<xs:enumeration value="Batch"/>
<xs:enumeration value="Service"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Update: OP has edited question to remove the use of xs:assert
and has stated in comments that validation must take place in C#. The answer to OP's question now becomes:
You cannot enforce a constraint that varies the requiredness of an element based on an attribute value using XSD 1.0, and Microsoft does not support XSD 1.1, therefore you must either relax your constraints or check them outside of your XSD.
Original XSD 1.1 answer
(Retained for benefit of future readers)
You're close, but your assertion,
<xs:assert test="count(./PackageArg[@type eq 'Batch']) eq 1"/>
tests for @type
on PackageArg
when it should test for @Type
on Application
.
The following XSD will validate your XML and enforce your attribute-dependent requirements:
XSD 1.1
<?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="Applications">
<xs:complexType>
<xs:sequence>
<xs:element name="Application" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:all>
<xs:element type="xs:string" name="ProjectDirName"/>
<xs:element type="xs:string" name="Project" minOccurs="0"/>
<xs:element type="xs:string" name="Version" minOccurs="0"/>
<xs:element type="xs:string" name="PackageArg" minOccurs="0"/>
<xs:element type="xs:string" name="OutputDirName"/>
</xs:all>
<xs:attribute type="xs:string" name="Name" use="optional"/>
<xs:attribute name="Type" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Web"/>
<xs:enumeration value="Batch"/>
<xs:enumeration value="Service"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:assert test="PackageArg or @Type != 'Batch'"/>
<xs:assert test="Version or @Type != 'Service'"/>
<xs:assert test="Project or not(@Type = 'Web' or @Type = 'Service')"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Be aware that Microsoft does not support XSD 1.1. (You've tagged your question with 'msxml').
来源:https://stackoverflow.com/questions/30606320/make-xml-elements-required-based-on-attribute-values-in-xsd