After importing a complextype in one xsd from another xsd, is it possible to have selected subelements of the complex type in the second xsd - xsd

After importing a complextype in one xsd from another xsd, is it possible to have selected subelements of the complex type in the second xsd
What I mean is :
I have first xsd. -> AddressFile.xsd .In AddressFile.xsd, there is a complex type IndividualAddress, with 5 subelemnts. In the next xsd, Individual.xsd , I am referring to the complext type IndividualAddress in AddressFile.xsd. But in Individual.xsd, I just want DoorNO , StreetNum and State from the complex Type IndividualAddress directly . Is that possible. Is there any restrictions I can use.
AddressFile.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://abc/DP/Address">
<xs:complexType name="IndividualAddress">
<xs:annotation>
<xs:documentation>Address of an individual
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="DoorNO" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="StreetNum" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="State" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Country" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Pin" type="xs:String"
nillable="true" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Individual.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:address="http://abc/DP/Address"
targetNamespace="http://abc/DP/Individual">
<xs:import namespace="http://abc/DP/Address"
schemaLocation="AddressFile.xsd"/>
<xs:complexType name="Individual">
<xs:annotation>
<xs:documentation>Address of an individual
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Name" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Age" type="xs:int"
nillable="true" minOccurs="0"/>
<xs:element name="DoorNO" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
<xs:element name="StreetNum" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
<xs:element name="State" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

Your best approach depends on what you are trying to accomplish.
If you want XSD-aware tools to know that complex type Individual is derived from complex type IndividualAddress, you can derive the one from the other. You will need to do so in two steps: a restriction step to get rid of the unwanted child elements of the base type and then an extension step to add more elements, at the end. (Not at the beginning.)
If you just want to reuse the elements, the creator of the base schema has done the best job they can to hinder you, by making all the children of IndividualAddress local types, which cannot be referred to from elsewhere. If they wanted to make reuse easy, or even possible, they would (a) make the elements in question top-level elements, and/or possibly (b) use named model groups to package up groups of useful elements to be used together.

Related

Create an XSD that supports something like web.config transforms or multi-tenant/configuration xml files

I have an Xml file like this:
<Configuration xmlns="http://schemas.benefittech.com/evolution/site">
<SiteSettings>
<ProfileGroup>TBOLoanPmtElection</ProfileGroup>
<AWSGroup>TBOLoanPmtElection_Admin</AWSGroup>
</SiteSettings>
</Configuration>
And I have an XSD file like this:
<?xml version="1.0" encoding="us-ascii" ?>
<xs:schema elementFormDefault="qualified" attributeFormDefault="unqualified" version="5.0"
xmlns="http://schemas.benefittech.com/evolution/site" targetNamespace="http://schemas.benefittech.com/evolution/site"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vs="http://schemas.benefittech.com/Visual-Studio-Intellisense" vs:friendlyname="Evolution Site Configuration">
<xs:element name="Configuration">
<xs:complexType>
<xs:all>
<xs:element name="SiteSettings" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="AWSGroup" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="ProfileGroup" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="LogActivityGroup" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
I want to enable my Xml to look something like the following to allow for 'environment overrides' (the E attribute on the env:* element):
<Configuration xmlns="http://schemas.benefittech.com/evolution/site" xmlns:env="http://schemas.benefittech.com/evolution/siteenvironment">
<SiteSettings>
<ProfileGroup>TBOLoanPmtElection</ProfileGroup>
<AWSGroup>TBOLoanPmtElection_Admin</AWSGroup>
<env:AWSGroup E="SecondEnvironment">TBOLoanPmtElection2_Admin</env:AWSGroup>
</SiteSettings>
</Configuration>
Is there a way to modify the XSD so that given EVERY element in my configuration, I want to optionally have a env:* version of it. Do I have to make a new schema file like below that is basically a duplicate of original except for the target namespace?
<?xml version="1.0" encoding="us-ascii" ?>
<xs:schema elementFormDefault="qualified" attributeFormDefault="unqualified" version="5.0"
xmlns="http://schemas.benefittech.com/evolution/siteenvironment" targetNamespace="http://schemas.benefittech.com/evolution/siteenvironment"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vs="http://schemas.benefittech.com/Visual-Studio-Intellisense" vs:friendlyname="Evolution Site Configuration">
<xs:element name="Configuration">
<xs:complexType>
<xs:all>
<xs:element name="SiteSettings" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="AWSGroup" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="E" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="ProfileGroup" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="E" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="LogActivityGroup" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="E" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
Is there a way to modify the XSD so that given EVERY element in my configuration, I want to optionally have a env:* version of it.
No, there is no elegant way to add, after each element, an optional element having the same name but a different namespace. You would need to add each such env:* element individually.
Do I have to make a new schema file like below that is basically a duplicate of original except for the target namespace?
Yes, but only if you stick to this plan of using a different namespace for the 'extension' elements. In your reply to my comment you said
I thought I'd need separate namespaces. I didn't want to change code everywhere that selects elements. For example, SiteConfig.Elements( "SiteSettings" ).Elements( "AWSGroup" ).FirstOrDefault(); Would continue to work without picking up the env:* elements. Then during the publish process, I would swap out the env:* properties everywhere and code would just work. What's your suggestion?
I've hardly written a line of C#, but according to https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.firstordefault?view=netcore-3.1 the FirstOrDefault() method returns the first element in the sequence or a default. So I think there is a much simpler approach that will not break the existing code...
On each element that needs to have option extension element(s):
Set maxOccurs="unbounded" (or "2", if you only want to allow one extension element)
Add the attribute "E" and make it optional (so that existing documents which omit it on the first occurrence are still valid).
The name "E" for the attribute is not ideal - I would pick something more descriptive if possible.

XSD field dependent on another field [duplicate]

I have an XSD to validate an XML file. The structure is as follows:
<root>
<child>
<size>2</size>
<childElement>Element 1</childElement>
<childElement>Element 2</childElement>
</child>
</root>
The number of childElements is dependent on the size provided i.e. if size was set as 3, not more than 3 childElements can be added.
I have tried using xs:alternative but it does not seem to work:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="child" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="size" type="xs:integer" maxOccurs="1"/>
<xs:element name="childElement" type="xs:string" maxOccurs="1">
<xs:alternative test="#size>1" maxOccurs="#size"/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Is there a way of using xs:alternative or another tag to achieve this, or is this outside the realm of possibility with XSD?
Design recommendation: If your XML design can still be changed, eliminate the size element and convey that information implicitly rather than explicitly. By eliminating the duplication of information, you'll not need to check that the duplication is consistent.
If your XML design cannot still be changed, or if you choose not to change it...
XSD 1.0
Not possible. Would have to be checked out-of-band wrt XSD.
XSD 1.1
Possible using xs:assert:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
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">
<xs:complexType>
<xs:sequence>
<xs:element name="child">
<xs:complexType>
<xs:sequence>
<xs:element name="size" type="xs:integer"/>
<xs:element name="childElement" maxOccurs="unbounded"/>
</xs:sequence>
<xs:assert test="count(childElement) = size"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

XSD: How to have (A*|B*), C?, (A*|B*)

I have a XSD with XML elements A, B, and C.
I would like these to appear in a parent element in this way:
A and B can appear any times, C only once, optionally.
The order does not matter, but A and B should ideally be "together",
(so it's rather (A*), C?, (B*) | (B*), C?, (A*)), but the "A and B together" is not necessary).
How can I achieve that with XSD?
Actual XSD what I have tried:
<!-- Hint -->
<xs:element name="hint">
<xs:complexType mixed="true">
<xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:choice>
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
But that gives me
cos-nonambig: <ns>:link and <ns>:link (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
Basically, the need is to have any mix of A, B, C, where C appears
only once.
XSD 1.1 Solution
<?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:complexType name="SolutionType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="A"/>
<xs:element name="B"/>
<xs:element name="C"/>
</xs:choice>
<xs:assert test="count(c) <= 1"/>
</xs:complexType>
</xs:schema>
The above xs:assertion assumes that you mean "C appears at most once" but can easily be adjusted to require C to appear exactly once.
A and B can appear any times, C only once, optionally. The order does
not matter, but A and B should ideally be "together"
XSD 1.0 Solution
You'll have to impose an ordering to avoid violating Unique Particle Attribution:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="SolutionType">
<xs:sequence>
<xs:element name="A" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="C" minOccurs="0"/>
<xs:element name="B" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
At least this achieves your preference toward keeping A and B together.
The "Unique Particle Attribution" basically means that every element during validation needs to be deterministically assignable to certain XSD "branch". And that can be checked when validating the XSD.
I found out that the (only?) way to avoid abiguity is to list all combinations of A,B,C in a <xs:choice>, while setting minOccurs="1" as appropriate to break the ambiguity. That gives quite a few choices, but for 3 elements, still doable.
This is for the case where I leave 'C' in the beginning:
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
<xs:choice>
<xs:sequence>
<xs:element ref="link" minOccurs="1" maxOccurs="unbounded" />
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:sequence>
<xs:element ref="tag" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:sequence/>
</xs:choice>
</xs:sequence>
Not closing this question, I believe there's a better option even in XSD 1.0.

XSD Schema - how to ensure that two simple elements either have values or do not have values together

please assist, this is what i want to achieve in validating my xml file:
<?xml version="1.0" encoding="UTF-8"?>
<worker>
<name>dingo</name>
<ssn>12345</ssn>
</worker>
I want to ensure that the two simple elements 'name' and 'ssn' either have values (as a group) or do not have any value (as a group). They cannot exist individually with a value.
I have to use an XSD schema, so cannot use other options i see suggestions sometimes: Relax NG etc.
I looked into creating a group for elements 'name' and 'ssn' but i am unable to find out how to create a restriction for this group to obtain my condition.
My current XSD file:
<xs:complexType name="worker">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" "maxOccurs="1">
<xs:element name="ssn" type="xs:positiveInteger" minOccurs="0" "maxOccurs="1">
</xs:sequence>
</xs:complexType>
<xs:complexType name="worker">
<xs:sequence minOccurs="0">
<xs:element name="name" type="xs:string">
<xs:element name="ssn" type="xs:positiveInteger">
</xs:sequence>
</xs:complexType>
You have to do
<xs:complexType name="worker">
<xs:group ref="workerGrp" minOccurs="0"/>
</xs:complexType>
<xs:group name="workerGrp">
<xs:sequence>
<xs:element name="name" type="xs:string">
<xs:element name="ssn" type="xs:positiveInteger">
</xs:sequence>
</xs:group>

Question about xsd. Elements inside complex type must be allowed in any order

If you look at the following xsd fragment you can conclude that the corresponding xml will first contain cars followed by busses eg:
car,car,bus,bus
HOWEVER I want the xml to be able to contain
car,bus,car,bus
What change do I need to make in the xsd below in order to achieve this?
<xs:element name="body">
<xs:complexType>
<xs:sequence>
<xs:element name="session" type="tns:session" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="tns:car" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="tns:bus" />
</xs:sequence>
</xs:complexType>
</xs:element>
It's a bit cumbersome, but you might achieve what you're looking for like this:
create a <xs:choice> element with your car and bus elements inside; this defines that one of the contained elements can be used
make sure to have the attribtues minOccurs=1 and maxOccurs=unbounded on that <xs:choice> - this gives you any number of either car or bus elements - any number, any combination
So your XML schema would look something like this (I added some stuff just to be able to generate a sample XML and verify it works - tweak as needed):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="body">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="CarType" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="BusType" />
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="CarType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="BusType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
<xs:element name="Capacity" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
use <xs:any> insted of <xs:sequence>

Resources