Here is an example from a xsd and a xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<config test2="true">
</config>
XSD
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="rules.xsd" xmlns="rules.xsd" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop">
<xs:element name="config">
<xs:complexType>
<xs:attribute name="test1" type="xs:boolean" default="false" />
<xs:attribute name="test2" type="xs:string" default="mary123" />
</xs:complexType>
</xs:element>
</xs:schema>
I can use this xsd to validate this xml in C# using this block of code
XmlDocument doc = new XmlDocument();
XmlTextReader schemaReader = new XmlTextReader(System.IO.Path.GetFullPath("Mi_XSD_here.xsd"));
XmlSchema schema = XmlSchema.Read(schemaReader, ValidationCallBack);
doc.Schemas.Add(schema);
doc.Load("Mi_XML_here.xml");
doc.Validate(ValidationCallBack);
The problem is: I have two default attributes in xsd, but when i run this code he doesn't insert the attributes in XmlDocument, the result is the same xml that i passed to the system.
The default attributes are not working and i cant figure why they aren't working, i do believe that exists other forms to solve this problem, i did find this but didn't worked
Extensions.Validate Method
obs: ValidationCallBack is some return on error function that i think isn't related to the problems
Your schema's target namespace is rules.xsd so your xml file needs to include that to validate against the schema. Also I'm assuming teste2 is a typo (since that doesn't conform to the schema) and you meant test2:
<config test2="" xmlns="rules.xsd" />
In this case only test1 will get added with a default since test2 is already set to an empty string.
Related
I am trying to create C# code from xsd file using XML Schema Definition Tool (Xsd.exe). But I am getting following error:
Schema validation warning: The 'http://www.w3.org/1999/xlink:href' attribute is not declared. Line 12, position 13.
Warning: Schema could not be validated. Class generation may fail or may produce incorrect results.
Error: Error generating classes for schema 'test'.
- The attribute href is missing.
xsd file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xl="http://www.w3.org/1999/xlink"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="">
<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="http://www.w3.org/1999/xlink.xsd"/>
<xs:element name="Image">
<xs:complexType>
<xs:attribute ref="xl:href" xmlns:xl="http://www.w3.org/1999/xlink"></xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Using the following command for generating file:
xsd.exe test.xsd /c /o:"."
I have following xml schema
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://www.MySchema.net" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="RootElement">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
and following xml's are validated against above schema:
Case 1: (Schema exception)
<?xml version="1.0" encoding="utf-8" ?> <RootElement11 name="Configuration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.MySchema.net Root" xmlns="http://www.MySchema.net">
</RootElement11>
Case 2: (No exception)
<?xml version="1.0" encoding="utf-8" ?>
<RootElement11 name="Configuration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.YourSchema.net Root" xmlns="http://www.YourSchema.net">
</RootElement11>
Case 3: (No exception)
<RootElement11 name="Configuration">
</RootElement11>
For Case 1, I get an expected exception that "The 'http://www.MySchema.net:RootElement1' element is not declared.", but Case 2 and Case 3 are validated without exception.
I wanted to know if there is a possibility to throw an exception when xml files with false namespaces or without namespaces are validated using XDocument.Validate method.
I found some info which use XmlReader with settings to throw these type of exception. I see two possibilites 1) Get back to XmlReader from XDocument, 2) Validate using XmlReader and use XDocument to do LINQ queries.
But is it possible to accomplish this without XmlReader.
The issue is that both cases 2 and 3 are valid per the schema - your schema doesn't have any opinion on elements in namespaces other than its targetNamespace.
XmlReader can return a warning for this, but there's no overload for XDocument that will do it. The snippet in your linked question uses an XmlReader wrapper around XDocument, I can't see why you'd have any issue with doing it this way.
I have two different xsd files associated to two different VS2010 projects.
The first one, named BasicTypes.xsd is "built" first using xsd.exe and generated classes are built in my NetToolbox.dll assembly.
When building the second one (named Entity.xsd), I need to reuse already generated class (Available in NetToolbox.dll) because types in Entity.xsd are defined in BasicTypes.xsd. This is in assembly EntityProvider.dll.
Moreover, at runtime, I must pass these objects from EntityProvider.dll to NetToolbox.dll so having the same class definition is mandatory (I think, maybe I am wrong here).
This question is very similar to the following link but the proposed answer is not possible for me (Altering machine.config) : Using xsd.exe to generate C# classes, how to specify an existing type?
I tried the proposed solution (By modifying machine.config) without success I really had a hard time correctly specifying the assembly in both machine.config and xsd.exe parameter.xml file.
<system.xml.serialization>
<schemaImporterExtensions>
<add type="SchemaImport.ADODBSchemaImporterExtension, SchemaImport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd583032ee337c41" />
</schemaImporterExtensions>
</system.xml.serialization>
For example, here are the two XSDs.
BasicTypes.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.tempuri.com/BasicTypes"
xmlns="http://www.tempuri.com/BasicTypes"
elementFormDefault="qualified">
<xs:complexType name="PositionType">
<xs:sequence>
<xs:element name="latitude" type="xs:double" />
<xs:element name="longitude" type="xs:double" />
<xs:element name="altitude" type="xs:double" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:schema>
and Entity.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.tempuri.com/Entity"
xmlns="http://www.tempuri.com/Entity"
elementFormDefault="qualified"
xmlns:bt="http://www.tempuri.com/BasicTypes">
<xs:import namespace="http://www.tempuri.com/BasicTypes" schemaLocation="directory\BasicTypes.xsd" />
<xs:element name="entity" type="EntityType" />
<xs:complexType name="EntityType">
<xs:complexContent>
<xs:extension base="bt:PositionType">
<xs:attribute name="id" type="xs:string" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Using any other third party tool than the one provided by the .NET framework (I'm at 4.0) or VS2010 is not an option (Security restrictions)
Thank you
You can register the schema importer extension in a configuration file for the xsd.exe utility itself instead of in the machine.config file.
To do this, make a copy of the xsd.exe application somewhere in your project's directory structure and create a file named xsd.exe.Config in the same directory. Add the lines to register the schema importer extension inside a configuration root element.
For your example, the xsd.exe.Config file would look like the following. Note that a name attribute is required in the add element, I've used the name of the extension class.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.xml.serialization>
<schemaImporterExtensions>
<add name="ADODBSchemaImporterExtension" type="SchemaImport.ADODBSchemaImporterExtension, SchemaImport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd583032ee337c41" />
</schemaImporterExtensions>
</system.xml.serialization>
</configuration>
I have made an XML schema to validate incoming xml files to validate if they are an Error or not.
I have some code that should return true when an xml file is valid, or false when it's not.
I have also made two XML files, one of which is valid, the other invalid. However, my code returns true for both of them, aka considers them both valid. How come? Where did I go wrong?
The schema:
XMLSchemaError.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XMLSchemaError"
targetNamespace="http://tempuri.org/XMLSchemaError.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchemaError.xsd"
xmlns:mstns="http://tempuri.org/XMLSchemaError.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="Error">
<xs:complexType>
<xs:sequence>
<xs:element name="Server_ID" type="xs:integer" />
<xs:element name="Prioritizing" type="xs:token" />
<xs:element name="Type" type="xs:token" />
<xs:element name="Thrown_by" type="xs:token" />
<xs:element name="Code" type="xs:string" />
<xs:element name="Text" type="xs:string" />
<xs:element name="Time_occured" type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code to validate the XML file:
XMLValidation.cs
private bool isValid = false;
public bool checkValid(string fileName)
{
try
{
var reader = XmlReader.Create("../../XMLFiles/" + fileName);
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(reader);
doc.Schemas.Add(null, "../../Model/XMLSchemaError.xsd");
doc.Validate(ValidationCallBack);
isValid = true;
}
catch
{
isValid = false;
}
System.Diagnostics.Debug.WriteLine("Check: " + isValid);
return isValid;
}
private void ValidationCallBack(object sender, ValidationEventArgs e)
{
throw new Exception();
}
The 2 XML files to validate:
Valid.xml
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Server_ID>4</Server_ID>
<Prioritizing>major</Prioritizing>
<Type>test error</Type>
<Thrown_by>test program</Thrown_by>
<Code></Code>
<Text></Text>
<Time_occurred>2016-02-9T12:34:56.7890</Time_occurred>
</Error>
Invalid.xml
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
As commenter Damien_The_Unbeliever points out, since your XML doesn't claim to contain any elements that are validated by the schema in question, both documents trivially pass validation. There's nothing in them to validate.
There are a variety of ways to correct the situation. The simplest is to just add a default XML namespace to the root element. E.g.:
<?xml version="1.0" encoding="UTF-8"?>
<note xmlns="http://tempuri.org/XMLSchemaError.xsd">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Having done that, the above XML now will fail validation according to your schema.
If you were to do the same thing to the "valid" XML, you would find that it too fails validation. This is for two reasons:
The schema misspells the word "occurred", while the XML does not. This can be fixed either by correcting the spelling the schema or by using the misspelling in the XML.
The XML has an incorrectly formatted dateTime value. The day-of-month field is specified using only a single digit, but the XML format requires two digits for both the month and day-of-month fields.
An actual valid XML, given the schema you've provided, would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<Error xmlns="http://tempuri.org/XMLSchemaError.xsd">
<Server_ID>4</Server_ID>
<Prioritizing>major</Prioritizing>
<Type>test error</Type>
<Thrown_by>test program</Thrown_by>
<Code></Code>
<Text></Text>
<Time_occured>2016-02-09T12:34:56.7890</Time_occured>
</Error>
(I've opted to misspell the element name in the XML, rather than fixing the schema, just because it simplifies the example XML required in this answer :) ).
i'm trying to learn a little bit XSD and I'm trying to create a XSD for this xml:
<Document>
<TextBox Name="Username" />
<TextBox Name="Password" />
</Document>
... so there's an element, which is an abstract complex type. Every element have elements and so on. Document and TextBox are extending Element.
I trid this:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Document">
<xs:complexType>
<xs:complexContent>
<xs:extension base="Element">
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:complexType name="Element" abstract="true">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Element" type="Element"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TextBox">
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="Name" type="xs:string" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
I compiled it to C# with Xsd2Code, and now I try to deserialize it:
var serializer = new XmlSerializer(typeof(Document));
var document = (Document)serializer.Deserialize(new FileStream("Document1.xml", FileMode.Open));
foreach (var element in document.Element1)
{
Console.WriteLine(((TextBox)element).Name);
}
Console.ReadLine();
and it dosen't print anything. When I try to serialize it like so:
var serializer = new XmlSerializer(typeof(Document));
var document = new Document();
document.Element1 = new List<Element>();
document.Element1.Add(new TextBox()
{
Name = "abc"
});
serializer.Serialize(new FileStream("d.xml", FileMode.Create), document);
...the output is:
<?xml version="1.0"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Element1>
<Element xsi:type="TextBox">
<Element1 />
<Name>abc</Name>
</Element>
</Element1>
</Document>
When it should be something like:
<?xml version="1.0"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TextBox Name="abc" />
</Document>
Any ideas how to fix the xsd or another code generator?
Thanks.
In the XSD code, look at the line where you declare an element named "Element". This element should be named as such <xs:element name="TextBox" /> if you want to use <TextBox/> in your XML files.
With the above change implemented, you could run xsd.exe /c YourFile.xsd to generate a C# class from the XSD. Include the generated file in your C# project and you'll be able to use it like this:
Document d = new Document();
d.TextBox = new TextBox[]
{
new TextBox() { Name = "Username" },
new TextBox() { Name = "Password" },
};
XmlSerializer ser = new XmlSerializer(typeof(Document));
ser.Serialize(Console.Out, d);
You'll also be able to deserialize the XML back into C# objects.
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TextBox xsi:type="TextBox" Name="Username" />
<TextBox xsi:type="TextBox" Name="Password" />
</Document>
Note the xsi:type attribute - because you declared your TextBox element to be of type Element you will have to provide which concrete type implementation to use when deserializing one of these elements. Out of curiosity I tried changing the XSD type of the element named TextBox to the TextBox type, but xsd.exe threw a StackOverflowException. I chuckled. It probably to do with the recursive type relationship between Element and TextBox, but maybe a different tool would handle it differently?