XML validation using XSD assertion condition - xsd-validation

I have below XML and XSD and I am getting some error while validation.
My XML
<parent>
<child1>Y</child1>
<child2>Y</child2>
</parent>
My XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="parent">
<xs:complexType>
<xs:sequence>
<xs:element name="child1" type="xs:string" />
<xs:element name="child2" type="xs:string" />
</xs:sequence>
<xs:assertion test="child1 != 'N' and child2 != 'N'" />
</xs:complexType>
</xs:element>
</xs:schema>`
The error I'm getting
s4s-elt-invalid-content.1: The content of '#AnonType_parent' is invalid. Element 'assertion' is invalid, misplaced, or occurs too often.
I want to pass the XML validation If I get other than 'N' value for child elements.
Can anyone suggest what I am doing wrong?

Related

Display XML Schema in SQL Query Result

I'm brand new to SQL and SQL Server Management Studio, so bear with me. Here's a shortened version of my query:
SELECT *
FROM [dbo].[BranchLocations] WHERE NOT (PropertyOwnerType IS NULL)
FOR XML PATH('LocationData'), ROOT('MainRoot')
This gives me exactly what I need except for the schema. I don't want to automatically generate a schema because the service to which I upload the XML data only accepts a specific schema structure, and I would prefer to control it.
My schema looks similar to this:
<xs:schema id="LocationData_ds" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="LocationData_ds" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="LocationData">
<xs:complexType>
<xs:sequence>
<xs:element name="EntityID" type="xs:string" />
<xs:element name="AddressLine" type="xs:string" minOccurs="0" />
<xs:element name="Locality" type="xs:string" minOccurs="0" />
<xs:element name="AdminDistrict" type="xs:string" minOccurs="0" />
<xs:element name="PostalCode" type="xs:string" minOccurs="0" />
<xs:element name="CountryRegion" type="xs:string" minOccurs="0" />
<xs:element name="Latitude" type="xs:double" minOccurs="0" />
<xs:element name="Longitude" type="xs:double" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//LocationData" />
<xs:field xpath="EntityID" />
</xs:unique>
</xs:element>
</xs:schema>
My query returns this:
<MainRoot>
<LocationData>
<EntityID>10010000</EntityID>
<AddressLine>1234 address<\/AddressLine>
<Locality>Converse</Locality>
<AdminDistrict>TX</AdminDistrict>
<PostalCode>12345</PostalCode>
<CountryRegion>US</CountryRegion>
</LocationData>
<LocationData>
<EntityID>70390000</EntityID>
<AddressLine>1234 address<\/AddressLine>
<Locality>Denver</Locality>
<AdminDistrict>CO</AdminDistrict>
<PostalCode>12345</PostalCode>
<CountryRegion>US</CountryRegion>
</LocationData>
...
<MainRoot>
And what I need is this:
(and I need ti include<?xml version="1.0" encoding="utf-8" standalone="yes"?> at the top as well)
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<MainRoot>
<xs:schema id="LocationData_ds" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="LocationData_ds" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="LocationData">
<xs:complexType>
<xs:sequence>
<xs:element name="EntityID" type="xs:string" />
<xs:element name="AddressLine" type="xs:string" minOccurs="0" />
<xs:element name="Locality" type="xs:string" minOccurs="0" />
<xs:element name="AdminDistrict" type="xs:string" minOccurs="0" />
<xs:element name="PostalCode" type="xs:string" minOccurs="0" />
<xs:element name="CountryRegion" type="xs:string" minOccurs="0" />
<xs:element name="Latitude" type="xs:double" minOccurs="0" />
<xs:element name="Longitude" type="xs:double" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//LocationData" />
<xs:field xpath="EntityID" />
</xs:unique>
</xs:element>
</xs:schema>
<LocationData>
<EntityID>10010000</EntityID>
<AddressLine>1234 address<\/AddressLine>
<Locality>Converse</Locality>
<AdminDistrict>TX</AdminDistrict>
<PostalCode>12345</PostalCode>
<CountryRegion>US</CountryRegion>
</LocationData>
<LocationData>
<EntityID>70390000</EntityID>
<AddressLine>1234 address<\/AddressLine>
<Locality>Denver</Locality>
<AdminDistrict>CO</AdminDistrict>
<PostalCode>12345</PostalCode>
<CountryRegion>US</CountryRegion>
</LocationData>
...
<MainRoot>
Looking through the documentation has led me here:
https://learn.microsoft.com/en-us/sql/t-sql/xml/insert-xml-dml?view=sql-server-ver15
It isn't working, but I think I might be on the right track.
These answers only relate to generating a schema:
convert database table into XML schema filehow to create XML schema from an existing database in SQL Server 2008
declare #BranchLocations table
(
EntityId varchar(20),
AddressLine varchar(20),
Locality varchar(20),
AdminDistrict varchar(20),
PostalCode varchar(20),
CountryRegion varchar(20),
PropertyOwnerType varchar(20)
);
insert into #BranchLocations(EntityId, AddressLine, Locality, AdminDistrict, PostalCode, CountryRegion, PropertyOwnerType)
values
('10010000', '1234 address', 'Converse', 'TX', '12345', 'US', 'x'),
('70390000', '1234 address', 'Denver', 'CO', '12345', 'US', 'x');
declare #myschema xml = N'<xs:schema id="LocationData_ds" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="LocationData_ds" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="LocationData">
<xs:complexType>
<xs:sequence>
<xs:element name="EntityID" type="xs:string" />
<xs:element name="AddressLine" type="xs:string" minOccurs="0" />
<xs:element name="Locality" type="xs:string" minOccurs="0" />
<xs:element name="AdminDistrict" type="xs:string" minOccurs="0" />
<xs:element name="PostalCode" type="xs:string" minOccurs="0" />
<xs:element name="CountryRegion" type="xs:string" minOccurs="0" />
<xs:element name="Latitude" type="xs:double" minOccurs="0" />
<xs:element name="Longitude" type="xs:double" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//LocationData" />
<xs:field xpath="EntityID" />
</xs:unique>
</xs:element>
</xs:schema>';
declare #res nvarchar(max);
select #res = N'<?xml version="1.0" encoding="utf-8" standalone="yes"?>' +
(
select *
from
(
select #myschema as '*'
union all
select
(
select *
FROM #BranchLocations
WHERE PropertyOwnerType is not null
FOR XML PATH('LocationData')
)
) as src
for xml path(''), root('Mainroot')
);
--test, show result
select 1 as tag, 0 as parent,
#res+'</foo>' as 'test!1!!xmltext'
for xml explicit;
--or
select #res = null;
declare #myxml xml = ( select *
FROM #BranchLocations
WHERE PropertyOwnerType is not null
and 1=2
FOR XML PATH('LocationData'));
--null result when empty resultset from table
select #res =
N'<?xml version="1.0" encoding="utf-8" standalone="yes"?>'
+(select #myschema,#myxml for xml path(''), root('Mainroot'))
where #myxml is not null;
select #res;
What you are looking for is called an Inline XSD Schema.
Here is BOL link: Generate an Inline XSD Schema
Unfortunately, it is very limited: "...You can specify XMLSCHEMA only in RAW and AUTO mode, not in EXPLICIT mode...". Same with the PATH mode.
Additional limitation is that SQL Server keeps XML as UTF-16, and strips an XML prolog from any XML data type internally.
To achieve what you need everything needs to be done manually, i.e. stitch together a prolog, XML Schema, and actual XML.

Extract value from column (xmltype)

We are using an ERP system. I'm newbie in XML.
In our system, we have a column XML_DATA which TYPE is xmltype(2000)
Schema:
<?xml version="1.0" ?>
- <xs:schema xmlns:xs=" " attributeFormDefault="qualified" elementFormDefault="qualified">
- <xs:element name="XK6">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element name="Product">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="Product_row" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
<xs:element name="DETAIL" type="Product_DETAIL" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
- <xs:simpleType name="Product_DETAIL">
- <xs:restriction base="xs:string">
<xs:maxLength value="1000" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
EDIT:
The XML:
<?xml version="1.0" encoding="utf-8" ?>
- <XP6>
+<collapsed_node>
+<collapsed_node>
+<collapsed_node>
- <Product>
- <Product_row>
<DETAIL>sometext </DETAIL>
</Product_row>
</Product>
</XP6>
How can i extract the column ?
Or need more data to do it ?
I want to get the Product_Detail value.
Use the "XMLTABLE" function (see https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions228.htm):
with d as (
select xmltype('
<XK6>
<Product>
<Product_row>
<DETAIL>First product detail</DETAIL>
</Product_row>
<Product_row>
<DETAIL>Second product detail</DETAIL>
</Product_row>
</Product>
</XK6>'
) as thexml from dual)
select detail from d,
xmltable('/XK6/Product/Product_row'
passing d.thexml
columns detail varchar2(100) path 'DETAIL')

From database to XML with data types

I am getting info from a database and adding it to a dataset. Then I create a XML with this info. I would want to have the XML, but also the datatypes in the header. Is it possible?
Here my code to write the XML:
//Fill dataset with different datatable:
//first datatable
DataSet imports = new DataSet("import");
NpgsqlDataAdapter daImport = new NpgsqlDataAdapter("select field1, field2 field3 from table1", _connPg);
daImport.FillSchema(imports, SchemaType.Source, "table1");
daImport.Fill(imports, "table1");
//seconda datatable
NpgsqlDataAdapter daImport1 = new NpgsqlDataAdapter("select field1, field2 field3 from table2", _connPg);
daImport1.FillSchema(imports, SchemaType.Source, "table2");
daImport1.Fill(imports, "table2");
//insert relation
DataRelation relation = new DataRelation("rel_rel1", imports.Tables["table1"].Columns["field1"], imports.Tables["table2"].Columns["field2"], true);
relation.Nested = true;
imports.Relations.Add(relation);
//write xml
imports.WriteXml("dataImport.xml");
And this is my xml
<?xml version="1.0" standalone="yes"?>
<import>
<table1>
<field1>1
</field1>
<field2>name
</field2>
<field3>surname
</field3>
<table2>
<field1>somedata
</field1>
<field2>1
</field2>
<field3>otherdata
</field3>
</table2>
</table1>
</import>
What I want?
I would want to get this XML but with the types of the fields defined in the header.
Thanks!
If you want the schema to be serialized with the data, just change :
imports.WriteXml("dataImport.xml");
to :
imports.WriteXml("dataImport.xml", XmlWriteMode.WriteSchema);
It will produce the following XML :
<?xml version="1.0" standalone="yes"?>
<import>
<xs:schema id="import" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="import" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="table1">
<xs:complexType>
<xs:sequence>
<xs:element name="field1" type="xs:int" />
<xs:element name="field2" type="xs:string" minOccurs="0" />
<xs:element name="field3" type="xs:boolean" minOccurs="0" />
<xs:element name="table2" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="field1" type="xs:int" />
<xs:element name="field2" type="xs:int" minOccurs="0" />
<xs:element name="field3" type="xs:double" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="table2_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//table2" />
<xs:field xpath="field1" />
</xs:unique>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//table1" />
<xs:field xpath="field1" />
</xs:unique>
<xs:keyref name="FK_T1T2" refer="Constraint1" msdata:IsNested="true">
<xs:selector xpath=".//table2" />
<xs:field xpath="field2" />
</xs:keyref>
</xs:element>
</xs:schema>
<table1>
<field1>0</field1>
<field2>test</field2>
<field3>false</field3>
<table2>
<field1>0</field1>
<field2>0</field2>
<field3>0</field3>
</table2>
<table2>
<field1>1</field1>
<field2>0</field2>
<field3>1.25</field3>
</table2>
</table1>
<table1>
<field1>1</field1>
<field2>test 2</field2>
<field3>true</field3>
</table1>
<table1>
<field1>2</field1>
<field2>test 3</field2>
<field3>false</field3>
<table2>
<field1>2</field1>
<field2>2</field2>
<field3>2.66</field3>
</table2>
</table1>
</import>

Can we add new attribute or change type of existing attribute to a "Referenced Element"?

In my XML schema I have an element being referenced tens of times by other elements but with different enumerated values for one of its attribute.
For now, instead of creating this element in global space and referencing it later, I am creating a new instance wherever it is needed. This approach has increased my schema size enormously because of repeated creation of almost same element many times. It also may have adverse effect on efficiency of the schema.
The only way that I see is to create element once and then reference it many times but my problem is: one of the attribute of this referenced element is required to have a different set of enumerations for each referencing element.
My question is:
Is it possible to to add an attribute to a "Referenced Element" in XML Schema?
Something like this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.myDomain.com" xmlns="http://www.myDomain.com" elementFormDefault="qualified">
<xs:simpleType name="myValues1">
<xs:restriction base="xs:string">
<xs:enumeration value="value1" />
<xs:enumeration value="value2" />
</xs:restriction>
</xs:simpleType>
<xs:element name="myElement">
<xs:complexType mixed="true">
<xs:attribute name="attr1" type="xs:string" />
<xs:attribute name="attr2" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="MainElement1">
<xs:complexType>
<xs:sequence>
<xs:element ref="myElement">
<xs:complexType>
<xs:attribute name="myAtt" type="myValues1" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="mainAtt1" />
</xs:complexType>
</xs:element>
</xs:schema>
Or can we change type of an existing attribute of a "Referenced Element" in XML Schema?
something like this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.myDomain.com" xmlns="http://www.myDomain.com" elementFormDefault="qualified">
<xs:simpleType name="myValues1">
<xs:restriction base="xs:string">
<xs:enumeration value="value1" />
<xs:enumeration value="value2" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="myValues2">
<xs:restriction base="xs:string">
<xs:enumeration value="value3" />
<xs:enumeration value="value4" />
</xs:restriction>
</xs:simpleType>
<xs:element name="myElement">
<xs:complexType mixed="true">
<xs:attribute name="attr1" type="xs:string" />
<xs:attribute name="attr2" type="xs:string" />
<xs:attribute name="myAtt" type="myValues1" />
</xs:complexType>
</xs:element>
<xs:element name="MainElement1">
<xs:complexType>
<xs:sequence>
<xs:element ref="myElement">
<xs:complexType>
<xs:attribute name="myAtt" type="myValues2" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="mainAtt1" />
</xs:complexType>
</xs:element>
</xs:schema>
You cannot override the content model of a referenced element. The point of the reference is that it points to exactly the same element every time.
If you really want the element to have different content, you are better off defining multiple global complex types and using them, rather than using an element reference:
<xs:complexType name="Type1" mixed="true">
<xs:attribute name="attr1" type="xs:string" />
<xs:attribute name="attr2" type="xs:string" />
<xs:attribute name="myAtt" type="myValues1" />
</xs:complexType>
<xs:complexType name="Type2" mixed="true">
<xs:complexContent>
<xs:extension base="Type1">
<xs:attribute name="myAtt2" type="myValues2" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="MainElement1">
<xs:complexType>
<xs:sequence>
<xs:element name="myElement" type="Type1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
I would not worry too much about performance. The reference to the global types will be resolved only once at schema load time.

Biztalk Composite Operations Service

I need to consume a Biztalk service that contains some composite operations. Essentially, one of my entities is in the form
<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://HRMApplication.Schemas.Customer" targetNamespace="http://HRMApplication.Schemas.Customer" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Customer">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomerCode" type="xs:string" />
<xs:element name="Name" type="xs:string" />
<xs:element name="Active" type="xs:int" />
<xs:element name="SubNumber" type="xs:string" />
<xs:element name="CustomerAccountNumber" type="xs:string" />
<xs:element name="AccountBranchCode" type="xs:string" />
<xs:element name="BranchLocationCode" type="xs:string" />
<xs:element name="Attention" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="Addresses">
<xs:complexType>
<xs:sequence>
<xs:element name="Street1" type="xs:string" />
<xs:element name="Street2" type="xs:string" />
<xs:element name="City" type="xs:string" />
<xs:element name="State" type="xs:string" />
<xs:element name="Zip" type="xs:string" />
<xs:element name="Country" type="xs:string" />
<xs:element name="Description" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="unbounded" name="PhoneNumbers">
<xs:complexType>
<xs:sequence>
<xs:element name="PhoneNumber" type="xs:string" />
<xs:element name="PhoneType" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
On the client side, I need to create a proxy for my service, and then create requests passing in customer objects and then displaying the response from the server in c#. How do I go about doing this in code please? Essentially, I am looking for code sample to help start me off of how to handle this sort of scenario given that when I generate a proxy using the ADD SERVICE REFERENCE option in visual studio, I get a proxy that requires I create a request object and then expect a response object.
Even within BizTalk, your composite operation will be wrapped around the response object. Your customer element will probably be created within the response object. The response object name and namespace is usually defined in the Adapter. What type of adapter are you using?