How to do Schematron validation over different xml files attributes - c#

I have one source1.xml file
<?xml version="1.0" encoding="utf-8" ?>
<list>
<author id="a1">Alice</author>
<author id="p1">Paul</author>
<author id="p2">Peter</author>
</list>
another source2.xml
<?xml version="1.0" encoding="utf-8" ?>
<list>
<author id="1"/>
<author id="a2"/>
<author id="p1"/>
</list>
I need to validate "id" attribute of the two xml files are having same values or not.
I can do it using the schematron as shown in this link ( http://zvon.org/xxl/SchematronTutorial/Examples/Example17/example.html)
So I have created on xsd file (source2.xsd) where my schematron is included as shown below
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="author">
<xs:annotation>
<xs:appinfo>
<sch:pattern name ="Compare AdaptiveDisplayDevice Id with DisplayDevice Id" xmlns:sch="http://www.ascc.net/xml/schematron">
<rule context="author">
<report test="document('source1.xml')//author[#id=current()/#id]">
Atrribute
<name path="document('source1.xml')//author[#id=current()/#id]"/> is forbidden in element
<name/>
</report>
</rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
My C# code to validation is as shown below
using System.Text;
using NMatrix.Schematron;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
/* setup schematron validation */
Validator validator = new Validator();
validator.AddSchema(#"D:\POC\ConsoleApplication1\ConsoleApplication1\source2.xsd");
/* run both validators at once */
validator.Validate(new XmlTextReader(#"D:\POC\ConsoleApplication1\ConsoleApplication1\source2.xml"));
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
If we observe two xml files , then while validation using schematron it should give me error at first two id values. However I am not getting any error ..
Can anyone help me here ....

Related

DataSet.ReadXml - Error “input string was not in a correct format”

There are two inputs to the code
XML file
XSD file
XML content
<MyFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<Attribute>
<AttributeName>Text1</AttributeName>
<AttributeContent>1</AttributeContent>
</Attribute>
<Attribute>
<AttributeName>Text1</AttributeName>
<AttributeContent>1</AttributeContent>
</Attribute>
</MyFile>
XSD content corresponding to this
<?xml version="1.0"?>
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="MyFile">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Attribute">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="AttributeName" type="xs:string" />
<xs:element minOccurs="0" name="AttributeContent" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
To read XML file in C#, I am using
DataSet ds = new DataSet();
ds.ReadXmlSchema(new MemoryStream(xmlSourceModel.File2Content));
foreach (DataTable tab in ds.Tables)
{
tab.BeginLoadData();
}
ds.ReadXml(new MemoryStream(xmlSourceModel.File1Content));
foreach (DataTable tab in ds.Tables)
{
tab.EndLoadData();
}
After this, I am expecting data in the dataset. And it does work.
Problem:
If I use XML content like following
<Attribute>
<AttributeName>Text1</AttributeName>
<AttributeContent></AttributeContent>
</Attribute>
Note here AttributeContent does not contain the value.
In this case ds.ReadXml() method give error
"Input string was not in a correct format."
How can we resolve this error so that we can pick null data?
or
Can we put some default data to avoid this error?
Basically, the XML file is now correct in this case.
Solution 1. Do not add the attribute which does not contain the value
<Attribute>
<AttributeName>Text1</AttributeName>
</Attribute>
Solution 2, Add xsi:nil="true" something like this
<Attribute>
<AttributeName>Text1</AttributeName>
<AttributeContent xsi:nil="true"></AttributeContent>
</Attribute>

How to generate xsd from xml in code behind

What I want to do is generating xsd file from xml which will be passed as string.
Sample:
Let's say we have that kind of xml passed in string:
<?xml version="1.0" encoding="utf-8"?>
<Sample>
<SampleId>41111111124</AnimalId>
<SampleName>string</SampleKind>
</Sample>
I would like to generate from this above xsd file from code behind:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Sample">
<xs:complexType>
<xs:sequence>
<xs:element name="SampleId" type="xs:unsignedLong" />
<xs:element name="SampleName" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
On msdn couldn't find such thing.
Is it even possible to make it in c# code behind?
Ok I found solution for this:
XmlSchemaInference is what I needed.

XML DATASET to be Validated

Hello all i have a scenario where i have
TWO XML FILES
one xml say "Books.xml" will create the schema for DATASET and i will use other XML file to load data into DATASET and all data in 2nd file will be inserted into DATASET
I have done these things but i m stuck at validating XML i want to validate 2nd xml file
means data entered into dataset should be exactly valid according to DATASET schema which will be according to First XML
i have tried it using XSD but i am not sure if XSD will be able to validate TYPE of data say if i have to input number and i have a string in my xml ,it should throw an exception
i have my xml like this
<DATA>
<HISTORY>
<book1>SOmebook</book1>
</HISTORY>
<POETRY>
<book2>Books</book2>
</POETRY>
</DATA>
and i am generating my XSD Using VisualStudio
to validate it im using a method something like this
XmlReaderSettings settings = //dont know exact settings
string data = null;
XmlReader Reader = XmlReader.Create(File.Open("C:\books.XML", FileMode.Open), settings, data);
DataSet ds = new DataSet();
ds.ReadXml(Reader);
Here's a quick example on how you can use a schema to validate. I'm using the shiporder example from W3Schools.
Schema:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string" minOccurs="0"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="orderid" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<shiporder orderid="889923">
<orderperson>John Smith</orderperson>
<shipto>
<name>Ola Nordmann</name>
<address>Langgt 23</address>
<city>4000 Stavanger</city>
<country>Norway</country>
</shipto>
<item>
<title>Empire Burlesque</title>
<note>Special Edition</note>
<quantity>1</quantity>
<price>10.90</price>
</item>
<item>
<title>Hide your heart</title>
<quantity>1</quantity> <!--Change to "one" to see validation error-->
<price>9.90</price>
</item>
</shiporder>
And here's the validation using Linq2XML:
XDocument document = XDocument.Load("shiporder.xml");
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create("schema.xsd"));
bool errors = false;
document.Validate(schemas, (o, e) =>
{
Console.WriteLine("Validation error: {0}", e.Message);
errors = true;
});
if (!errors)
{
Console.WriteLine("XML document successfully validated.");
}
else
{
Console.WriteLine("XML document does not validate.");
}
Change the value of of the <quantity> node as mentioned in the comment in order to see how the XML does not validate because of invalid type.

How do you generate xsd namespace prefixes in the resulting output file?

I've gone over multiple topics and solutions that talk specifically about this issue. None have worked or I fail to understand what I am doing wrong.
I would like for the namespace prefixes to accompany the element names in the resulting xml output file.
I'm am using the XSD command with Visual Studio 2008 from the VS Command Prompt
Here's my xsd schema for Trial.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Junk"
targetNamespace="http://www.opengis.net/kml/2.2"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:import namespace="http://www.google.com/kml/ext/2.2" schemaLocation="TestSchema.xsd" />
<!-- Start LookType -->
<xs:complexType name="LookType">
<xs:sequence>
<xs:element ref="gx:TimeSpan" minOccurs="0" />
<xs:element name="longitude" type="xs:string" />
</xs:sequence>
</xs:complexType>
<!-- End LookType -->
<xs:element name="Te" type="LookType" />
</xs:schema>
Here's my xsd schema for TestSchema.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="TestSchema"
targetNamespace="http://www.google.com/kml/ext/2.2"
xmlns="http://www.google.com/kml/ext/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="TimeSpan" type="gx:GXTimeSpanType" />
<!-- Start GXTimeSpanType -->
<xs:complexType name="GXTimeSpanType">
<xs:sequence>
<xs:element name="begin" type="xs:string" />
<xs:element name="end" type="xs:string" />
</xs:sequence>
</xs:complexType>
<!-- End GXTimeSpanType -->
</xs:schema>
I´m generating the resulting class file Trial.cs by using xsd TestSchema.xsd ./Trial.xsd /c /l:cs /n:T
In a program I assign these junk values and write them to file using XmlDocument, XmlSerializer and FileStream
T.LookType te = new T.LookType();
te.longitude = "34.444";
te.TimeSpan = new T.GXTimeSpanType();
te.TimeSpan.begin = "2010-02-26T20:22:00Z";
te.TimeSpan.end = "2010-02-26T20:23:42Z";
I've excluded the method that saves out the file using XmlDocument, XmlSerializer and FileStream as it is a little thicker then I'd like to post unless that is part of the problem.
This is what I get in the resulting file
<?xml version="1.0" encoding="utf-16"?>
<Te xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.opengis.net/kml/2.2">
<TimeSpan xmlns="http://www.google.com/kml/ext/2.2">
<begin>2010-02-26T20:22:00Z</begin>
<end>2010-02-26T20:23:42Z</end>
</TimeSpan>
<longitude>34.444</longitude>
</Te>
This is what I want in the resulting file. Notice the gx:TimeSpan element and the xmlns:gx namespace definition being added to the main Te element.
<?xml version="1.0" encoding="utf-16"?>
<Te xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2">
<gx:TimeSpan>
<begin>2010-02-26T20:22:00Z</begin>
<end>2010-02-26T20:23:42Z</end>
</gx:TimeSpan>
<longitude>34.444</longitude>
</Te>
It doesn't matter on which element the prefixes are declared on, as long as they're declared before they are used. Any code that doesn't like this is broken.
Perhaps because it doesn't matter, XML Schema has no way to influence on which element the prefixes are declared, or which prefix is used.

Exception when loading partial xml data into xsd dataset

I have the following .xsd code:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" id="MyDataSet">
<xs:element name="Row">
<xs:complexType>
<xs:sequence>
<xs:element name="Number" type="xs:int"/>
<xs:element name="Item" type="xs:string"/>
<xs:element name="Comment" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
And the following .xml file:
<?xml version="1.0" standalone="yes"?>
<MyDataSet>
<Row>
<Number>1</Number>
<Item>first</Item>
</Row>
</MyDataSet>
Since the "Comment" tag is missing in the xml file, I get an exception when running:
MyDataSet myDataSet = new MyDataSet();
myDataSet.ReadXml(xmlFilePath);
The exception is: "Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints."
How can I define the .xsd to be able to receive partial xml data and fill null or any default value when a tag is missing?
Got it... I needed to add the attribute "Nillable" with the value of "true" to the fields that may not arrive in the xml.

Categories

Resources