I have to read an XML from file, which is:
<?xml version="1.0" encoding="UTF-16"?>
<KyactusProfileClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<username>sadasdsad</username>
<userid>0067AA87BF9AD466792E1A20F6AAB7F</userid>
<useDefaultFolder>false</useDefaultFolder>
<autoAcceptDownloads>false</autoAcceptDownloads>
<visible>false</visible>
</KyactusProfileClass>
I read it using following code:
using (var xmlReader = XmlReader.Create(pathXML))
{
Console.WriteLine(File.ReadAllText(pathXML));
schemas.Add(null, xmlReader);
}
But I get following error:
System.Xml.Schema.XmlSchemaException: 'The root element of W3C XML Schema must be < schema > and its namesapce must be 'http://www.w3.org/2001/XMLSchema'.'
I generated that XML using a XML serializer and XSD Schema validator:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="kyactusprofile" type="kyactusprofile" />
<xs:complexType name="kyactusprofile" >
<xs:sequence>
<xs:element type="xs:string" name="username" maxOccurs="1" minOccurs="1"/>
<xs:element type="xs:string" name="userid" maxOccurs="1" minOccurs="1"/>
<xs:element type="xs:boolean" name="useDefaultFolder" maxOccurs="1" minOccurs="1"/>
<xs:element type="xs:string" name="defaultFolder" maxOccurs="1" minOccurs="1"/>
<xs:element type="xs:boolean" name="autoAcceptDownloads" maxOccurs="1" minOccurs="1"/>
<xs:element type="xs:boolean" name="visible" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Hers is the stack trace:
System.Xml.Schema.XmlSchemaException
HResult=0x80131941
Message=L'elemento radice di W3C XML Schema deve essere <schema> e il suo spazio dei nomi deve essere 'http://www.w3.org/2001/XMLSchema'.
Source=System.Xml
StackTrace:
at System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
at System.Xml.Schema.XmlSchemaSet.SendValidationEvent(XmlSchemaException e, XmlSeverityType severity)
at System.Xml.Schema.XmlSchemaSet.ParseSchema(String targetNamespace, XmlReader reader)
at System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace, XmlReader schemaDocument)
at Kyactus.XmlManager.GestoreXml.ValidateXmlWithXsd(String pathXML) in C:\Users\Cristiano\Documents\Visual Studio 2017\Projects\progetto-pds\visual-studio\Kyactus\Kyactus\XmlManager\GestoreXml.cs:line 249
at Kyactus.XmlManager.GestoreXml.UnmarshallProfile() in C:\Users\Cristiano\Documents\Visual Studio 2017\Projects\progetto-pds\visual-studio\Kyactus\Kyactus\XmlManager\GestoreXml.cs:line 178
at Kyactus.XmlManager.GestoreXml..ctor() in C:\Users\Cristiano\Documents\Visual Studio 2017\Projects\progetto-pds\visual-studio\Kyactus\Kyactus\XmlManager\GestoreXml.cs:line 64
at Kyactus.App..ctor() in C:\Users\Cristiano\Documents\Visual Studio 2017\Projects\progetto-pds\visual-studio\Kyactus\Kyactus\App.xaml.cs:line 21
at Kyactus.App.Main()
You are most likely reading the XML
<?xml version="1.0" encoding="UTF-16"?>
<KyactusProfileClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<username>sadasdsad</username>
<userid>0067AA87BF9AD466792E1A20F6AAB7F</userid>
<useDefaultFolder>false</useDefaultFolder>
<autoAcceptDownloads>false</autoAcceptDownloads>
<visible>false</visible>
</KyactusProfileClass>
with the XmlReader and try to add it as XmlSchema. That's the wrong approach, it's not a schema! You have to read your XSD, then no Exception will appear.
Related
I have a sample to read a xml schema set for a xml file which contains different namespaces. For this i can get different schema for each namespace as i explained below.
Sample File:
<?xml version="1.0" encoding="utf-8"?>
<data xmlns:d="http://sampleschema/dataservices" xmlns:m="http://sampleschema/dataservices/metadata">
<content>
<m:properties>
<d:CustomerID>ALFKI</d:CustomerID>
<d:CompanyName>Alfreds Futterkiste</d:CompanyName>
</m:properties>
</content>
</data>
Sample Code to get XML Schema Set:
strFileName = #"C:\Sample\Sample.xml";
XmlReader reader = XmlReader.Create(strFileName);
XmlSchemaInference schema = new XmlSchemaInference();
XmlSchemaSet schemaSet = schema.InferSchema(reader);
It gives three different types of schemas while using the above code. But my requirement will be i need a single schema for the entire xml file which contain any number of namespaces in it. I have checked with possibilities of codes in msdn and stack overflow. I can't find any proper solution for this.
The expected schema output will be like below.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="content">
<xs:complexType>
<xs:sequence>
<xs:element name="m:properties">
<xs:complexType>
<xs:sequence>
<xs:element name="d:CustomerID" type="xs:string"></xs:element>
<xs:element name="d:CompanyName" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="xmlns:d" type="xs:string"></xs:attribute>
<xs:attribute name="xmlns:m" type="xs:string"></xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Any one can help to achieve this requirement.
Thanks in advance.
Try something like this :
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:m="http://www.w3.org/2001/XMLSchema" xmlns:d="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="content">
<m:complexType>
<m:sequence>
<m:element name="properties">
<d:complexType>
<d:sequence>
<d:element name="CustomerID" type="xs:string"></d:element>
<d:element name="CompanyName" type="xs:string"></d:element>
</d:sequence>
</d:complexType>
</m:element>
</m:sequence>
</m:complexType>
</xs:element>
</xs:sequence>
<d:attribute name="xmlns_d" type="d:string"></d:attribute>
<m:attribute name="xmlns_m" type="d:string"></m:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
I'm using this xml sample generator to create a sample of the following XSD files:
Main XSD:
<?xml version="1.0" ?>
<xs:schema xmlns:pur="http://NamespaceTest.com/Purchase"
xmlns:cmn="http://NamespaceTest.com/CommonTypes"
xmlns:cust="http://NamespaceTest.com/CustomerTypes"
targetNamespace="http://NamespaceTest.com/Purchase"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:import schemaLocation="test2.xsd"
namespace="http://NamespaceTest.com/CommonTypes" />
<xs:import schemaLocation="test.xsd"
namespace="http://NamespaceTest.com/CustomerTypes" />
<xs:element name="CustomerDetails" type="cust:CustomerType" />
</xs:schema>
Customer XSD:
<?xml version="1.0" ?>
<xs:schema xmlns:cmn="http://NamespaceTest.com/CommonTypes"
targetNamespace="http://NamespaceTest.com/CustomerTypes"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:import schemaLocation="test2.xsd"
namespace="http://NamespaceTest.com/CommonTypes" />
<xs:complexType name="CustomerType">
<xs:sequence>
<xs:element name="Name" type="xs:string" />
<xs:element name="DeliveryAddress" type="cmn:AddressType" />
<xs:element name="BillingAddress" type="cmn:AddressType" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Common Types XSD:
<?xml version="1.0" ?>
<xs:schema targetNamespace="http://NamespaceTest.com/CommonTypes"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:complexType name="AddressType">
<xs:sequence>
<xs:element name="Line1" type="xs:string" />
<xs:element name="Line2" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
The result of the following commands is a xml with a namespace prefix I don't expected, namely xmlns="http://NamespaceTest.com/CustomerTypes instead of xmlns="http://NamespaceTest.com/CommenTypes for the delivery address and billing address:
StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings { Indent = true };
XmlWriter writer = XmlWriter.Create(builder, settings);
XmlQualifiedName qname = new XmlQualifiedName("CustomerDetails", #"http://www.test.de");
XmlSampleGenerator generator = new XmlSampleGenerator(#"C:\Users\test.xsd", qname);
generator.WriteXml(writer);
Console.WriteLine(builder.ToString());
Result xml:
<?xml version="1.0" encoding="utf-16"?>
<CustomerDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://NamespaceTest.com/Purchase">
<Name xmlns="http://NamespaceTest.com/CustomerTypes">Name1</Name>
<DeliveryAddress xmlns="http://NamespaceTest.com/CustomerTypes">
<Line1 xmlns="http://NamespaceTest.com/CommonTypes">Line11</Line1>
<Line2 xmlns="http://NamespaceTest.com/CommonTypes">Line21</Line2>
</DeliveryAddress>
<BillingAddress xmlns="http://NamespaceTest.com/CustomerTypes">
<Line1 xmlns="http://NamespaceTest.com/CommonTypes">Line11</Line1>
<Line2 xmlns="http://NamespaceTest.com/CommonTypes">Line21</Line2>
</BillingAddress>
</CustomerDetails>
I wanted to find a xsd file for MS office Docx's [Content_Types].xml file (Where can I find the XSDs of DOCX XML files?)
I got an answer, but I've found that for some reason this xsd cause all of my xml files to pass validation test
This is my xml file:
<?xml version="1.0" encoding="utf-8"?>
<Export_toLab Sending_Site="3">
<Tracker Tracker_ID="55" Booklet_Type="3">
<Booklet Booklet_ID="542"/>
</Tracker>
</Export_toLab>
This is the xsd file (schema of MS office Docx's [Content_Types].xml):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns="http://schemas.openxmlformats.org/package/2006/content-types"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/content-types"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xs:element name="Types" type="CT_Types"/>
<xs:element name="Default" type="CT_Default"/>
<xs:element name="Override" type="CT_Override"/>
<xs:complexType name="CT_Types">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Default"/>
<xs:element ref="Override"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="CT_Default">
<xs:attribute name="Extension" type="ST_Extension" use="required"/>
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
</xs:complexType>
<xs:complexType name="CT_Override">
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
<xs:attribute name="PartName" type="xs:anyURI" use="required"/>
</xs:complexType>
<xs:simpleType name="ST_ContentType">
<xs:restriction base="xs:string">
<xs:pattern
value="(((([\p{IsBasicLatin}-[\p{Cc}\(\)<>#,;:\\"/\[\]\?=\{\}\s\t]])+))/((([\p{IsBasicLatin}-[\p{Cc}\(\)<>#,;:\\"/\[\]\?=\{\}\s\t]])+))((\s+)*;(\s+)*(((([\p{IsBasicLatin}-[\p{Cc}\(\)<>#,;:\\"/\[\]\?=\{\}\s\t]])+))=((([\p{IsBasicLatin}-[\p{Cc}\(\)<>#,;:\\"/\[\]\?=\{\}\s\t]])+)|("(([\p{IsLatin-1Supplement}\p{IsBasicLatin}-[\p{Cc}"\n\r]]|(\s+))|(\\[\p{IsBasicLatin}]))*"))))*)"
/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ST_Extension">
<xs:restriction base="xs:string">
<xs:pattern
value="([!$&'\(\)\*\+,:=]|(%[0-9a-fA-F][0-9a-fA-F])|[:#]|[a-zA-Z0-9\-_~])+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
This is the validation code:
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("http://schemas.openxmlformats.org/package/2006/content-types", "opc-contentTypes.xsd");
XDocument doc = XDocument.Load("MyFile.xml");
string msg = "";
doc.Validate(schemas, (o, e) => {msg += e.Message + Environment.NewLine;});
Console.WriteLine(msg == "" ? "Document is valid" : "Document invalid: " + msg);
Why the xml file is deteced as a valid xml?
Thanks
I think you may have the same issue as here:
XDocument.Validate is always successful
To summarise, the validate method does not raise an error for the nodes it does not know about. You should simply check before validating that the namespace of the xml is the same as the schema - if not its definitely a fail so no need to validate.
I have the following XSD files:
ReadFile.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="elsag:lprcore" elementFormDefault="qualified" targetNamespace="elsag:lprcore" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="Read.xsd" />
<xs:element name="reads" type="ReadFile" />
<xs:complexType name="ReadFile">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="read" nillable="true" type="read">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Read.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="elsag:lprcore" elementFormDefault="qualified" targetNamespace="elsag:lprcore" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="Snapshot.xsd"/>
<xs:include schemaLocation="GPS.xsd"/>
<xs:simpleType name="guid">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" />
</xs:restriction>
</xs:simpleType>
<xs:element name="read" type="read"/>
<xs:complexType name="read">
<xs:complexContent mixed="false">
<xs:extension base="snapshot">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="timestamp" type="xs:dateTime" />
<xs:element minOccurs="1" maxOccurs="1" name="plate" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="state" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="1" name="confidence" type="xs:int" />
<xs:element minOccurs="1" maxOccurs="1" name="overviews">
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="snapshot" type="snapshot"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="1" maxOccurs="1" name="gps" type="gps" />
</xs:sequence>
<xs:attribute name="id" type="guid" use="required" />
<xs:attribute name="camera" type="xs:string" use="required" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Please note that there are more files that make up the XSD, but I don't believe they're relevant to the problem so I did not include them.
I'm using the following code to validate XML files being processed. I want to reject any file that doesn't validate without errors:
StringBuilder validationErrors = new StringBuilder();
inDoc.Validate( schemas, ( o, e ) => {
validationErrors.AppendLine( e.Message );
} );
if ( !string.IsNullOrWhiteSpace( validationErrors.ToString() ) ) {
. . .
}
I've passed the following XML file to the code above and the code does not generate any validation error messages for it.
<read>
<timestamp>2015-07-17T16:20:18.1540000-04:00</timestamp>
<plate>FED456</plate>
</read>
I would have thought that the lack of the reads tag surrounding the read tag would have caused the XML to fail validation. Is the problem in the validation code or is it in the XSD or is this normal?
EDIT:
Here is the code that initializes the schemas variable:
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add( "elsag:lprcore", #"XML\ReadFile.xsd" );
Because you have defined
<xs:element name="read" type="read"/>
the read element is a valid root element for your XML. Every element which is an immediate child of <xs:schema> is eligible for being a root element (even those in an included schema).
Thanks to information posted in the answer by Glorfindel and the link posted by overslacked, I've been able to get the XML validation in my program to work.
The problem was that the program would not flag an XML file that does not contain a namespace as invalid. The cause is that the XDocument.Validate extension method creates an XmlReader object whose XmlReaderSettings property does not contain the ReportValidationWarnings flag. As a result, the ValidationEventHandler delegate passed to the method is not called for these files.
To make the validation logic work, I defined a new extension method that includes the flag:
internal static class XmlValidationExtension {
public static void ValidateWithWarnings( this XDocument doc, XmlSchemaSet schemas, ValidationEventHandler validationCallback ) {
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add( schemas );
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler( validationCallback );
XmlReader reader = XmlReader.Create( doc.CreateReader(), settings );
while ( reader.Read() ) ;
}
}
This is essentially the same exact code from the question linked to by overslacked, but where the XmlReader is created by calling the XDocment object's CreateReader method.
This code now considers any XML file which does not use the correct namespace to be invalid. Any other part of the XML that does not match the XSD is also flagged.
I've been searching for an answer for quite some time without any luck.
I'm using NDbUnit for my test data and I want to be able to generate my XSD files automatically. I don't want to have to regenerate my XSD files each time I add a new property to my classes. So my plan is to automatically generate the XSD files using the XsdDataContractExporter class since some of my classes contain IList and I got some errors using the xml serializer.
this is the code I got so far:
XsdDataContractExporter exporter = new XsdDataContractExporter();
exporter.Export(typeof(Supplier));
//XmlQualifiedName xmlQualifiedName = exporter.GetRootElementName(typeof(Supplier));
foreach (XmlSchema schema in exporter.Schemas.Schemas()) {
XmlWriter writer = XmlWriter.Create(String.Format(#"..\..\data\{0}.xsd", GetSchemaName(schema)), new XmlWriterSettings() {
ConformanceLevel = ConformanceLevel.Auto,
Encoding = Encoding.UTF8,
Indent = true,
OmitXmlDeclaration = false
});
foreach (XmlSchemaObject include in schema.Includes) {
XmlSchemaImport importedSchema = include as XmlSchemaImport;
if (importedSchema != null) {
ArrayList lst = new ArrayList(exporter.Schemas.Schemas(importedSchema.Namespace));
XmlSchema actualImportedSchema = (XmlSchema)lst[0];
importedSchema.Schema = actualImportedSchema;
importedSchema.SchemaLocation = Path.GetFullPath(String.Format(#"..\..\data\{0}.xsd", GetSchemaName(actualImportedSchema)));
}
}
schema.Write(writer);
writer.Close();
}
DataSet ds = new DataSet();
ds.ReadXmlSchema(#"..\..\data\business.model.supplier.xsd");
the problem is that I get an error when reading the schema which is:
failed: System.InvalidOperationException : Nested table 'SupplierCategory' which inherits its namespace cannot have multiple parent tables in different namespaces.
The bottom line is, I want to use a dynamically generated XSD file from a type to use with NDBUnit to populate my database with test data. Is this the right approach ? This is the schema that are generated and that gives my the error:
Supplier:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/Business.Model.Supplier" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/Business.Model.Supplier" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="C:\dev\skeleton\branches\dev\src\testconsole\data\business.model.supplier.category.xsd" namespace="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" />
<xs:import schemaLocation="C:\dev\skeleton\branches\dev\src\testconsole\data\arrays.xsd" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<xs:complexType name="Supplier">
<xs:sequence>
<xs:element minOccurs="0" name="Categories" nillable="true" xmlns:q1="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" type="q1:ArrayOfSupplierCategory" />
<xs:element minOccurs="0" name="Comments" nillable="true" xmlns:q2="http://schemas.microsoft.com/2003/10/Serialization/Arrays" type="q2:ArrayOfstring" />
<xs:element minOccurs="0" name="Description" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="Name" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="Supplier" nillable="true" type="tns:Supplier" />
</xs:schema>
SupplierCategory:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="ArrayOfSupplierCategory">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="SupplierCategory" nillable="true" type="tns:SupplierCategory" />
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfSupplierCategory" nillable="true" type="tns:ArrayOfSupplierCategory" />
<xs:complexType name="SupplierCategory">
<xs:sequence>
<xs:element minOccurs="0" name="Description" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="SupplierCategory" nillable="true" type="tns:SupplierCategory" />
</xs:schema>
Any advice would be great !
Thx,
Franck
See the list of suggestions in this post Getting XML Schema from MS SQL Database (specifically the top-voted answer) but also note my suggestion of using MyGeneration to achieve the same thing.
That's a problem I've also been facing quite a time later, as we were using NDbUnit for integration tests in our project – ended up with a custom library, which doesn't need a schema to be defined separately, it reads it from database on its own. Library is Reseed.