I am struggling with parsing XPathDocument with XPathNavigator where XML document contains xmlns tag, but no namesapce prefix is used.
<?xml version="1.0" encoding="UTF-8"?>
<Order version="1" xmlns="http://example.com">
<Data>
<Id>1</Id>
<b>Aaa</b>
</Data>
</Order>
SelectSingleNode method requires namespace manager with namespace defined.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nav.NameTable);
nsmgr.AddNamespace("ns","http://example.com");
As a result I have to start using ns prefix in all XPath expressions, although the original XML file does not use prefixes, for e.g.:
nav.SelectSingleNode("/ns:Order/ns:Data/ns:Id", nsmgr)
This adds an unnecessary complexity.
Is there any way to push XPathNavigator to ignore namespace and its prefixes? Ot at least use of prefixes, as namespace definition itself exists only once, so not much effort
The XML has a default namespace. So each and every XML element is bound to it, visible or not.
It is better to use LINQ to XML.
It is a preferred XML API, and available in the .Net Framework since 2007.
c#
void Main()
{
XDocument xdoc = XDocument.Parse(#"<Order version='1' xmlns='http://example.com'>
<Data>
<Id>1</Id>
<b>Aaa</b>
</Data>
</Order>");
XNamespace ns = xdoc.Root.GetDefaultNamespace();
foreach (XElement elem in xdoc.Descendants(ns + "Data"))
{
Console.WriteLine("ID: {0}, b: {1}"
, elem.Element(ns + "Id")?.Value
, elem.Element(ns + "b")?.Value);
}
}
I have a WCF service with a basicHttpBinding endpoint. One of the types included in one of the data contracts implements IXmlSerializable and includes an XmlSchemaProvider that returns the contents of an Xsd file embedded in the assembly. When I hit the endpoint in the browser, the Wsdl generation fails, "XmlSchemaException: The 'http://www.w3.org/XML/1998/namespace:lang' attribute is not declared." There is an issue compiling the embedded Xsd file.
I did some research and discovered that the DataContractSerializer (and XsdDataContractExporter) do not support all serializable types (http://msdn.microsoft.com/en-us/library/ms731923(v=vs.110).aspx). I suspect this behavior is at work here because the embedded Xsd includes a required attribute.
I also dotPeeked the XsdDataContractExporter code and found that get_Schemas compiles the imported schema set before returning and this is what is failing.
As a workaround, I modified the WCF service to use XmlSerializer instead of DataContractSerializer and the Wsdl generates OK. Has anyone experienced this behavior before? Thoughts?
Here is a console application and sample Xsd that will reproduce the error.
using System;
using System.Resources;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace SchemaCompiler
{
public class Program
{
static void Main()
{
var exporter = new XsdDataContractExporter();
if (!exporter.CanExport(typeof(Foo)))
return;
exporter.Export(typeof(Foo));
// The following line will throw XmlSchemaException: The 'http://www.w3.org/XML/1998/namespace:lang' attribute is not declared.
var schemaSet = exporter.Schemas;
Console.WriteLine(schemaSet.IsCompiled);
}
[Serializable]
[XmlSchemaProvider("GetSchema")]
public class Foo : IXmlSerializable
{
private static XmlSchema _xmlSchema;
public String Bar { get; set; }
public String Language { get; set; }
public static XmlQualifiedName GetSchema(XmlSchemaSet schemaSet)
{
var type = typeof(Foo);
var xsdFileStream = type.Assembly.GetManifestResourceStream(type, "Foo.xsd");
if (xsdFileStream == null) throw new MissingManifestResourceException(
"The embedded resource Foo.xsd was not found. For more information, http://support.microsoft.com/kb/319292");
_xmlSchema = XmlSchema.Read(xsdFileStream, null);
schemaSet.Add(_xmlSchema);
return new XmlQualifiedName(type.Name, "http://tempuri.org/Foo.xsd");
}
#region IXmlSerializable Members
public XmlSchema GetSchema()
{
return _xmlSchema;
}
public void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public void WriteXml(XmlWriter writer)
{
throw new NotImplementedException();
}
#endregion
}
}
}
And here is the sample Xsd file that you will need to embed in the assembly:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Foo" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://tempuri.org/Foo.xsd" elementFormDefault="qualified">
<xs:import namespace="http://www.w3.org/XML/1998/namespace" />
<xs:complexType name="Foo" mixed="false">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="unbounded" name="Value">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute ref="xml:lang" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Your analysis may be correct. But the error message complains about an undeclared attribute, not about an unsupported construct, so I wonder if there is another explanation.
Your schema document should be fine if the software that uses it knows where to find a schema document for the namespace http://www.w3.org/XML/1998/namespace. But most XSD software I am familiar with doesn't have built-in knowledge of that namespace. I wonder if your initial setup would work better if you changed the import to read something like this:
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
N.B. W3C serves schemas and DTDs very very slowly (it's a long story), so you may prefer (even just for testing, and certainly for serious work) to make a local copy of the schema document for the XML namespace (the URI is given in the example) and point to your local copy instead.
I have generated a set of classes using xsd.exe and created an XML document from the resulting generated code. I would now like to validate the serialized class instance against the original xsd.
My XML is like this:
<?xml version="1.0" encoding="UTF-8"?>
<MyRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-- rest of XML document here
</MyRoot>
My XSD is like this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="MyRoot" type="MyRootType"/>
-- MyRootType definition and rest of XSD
</xs:schema>
When I try to validate the XML using a XmlReader, I get the following error:
"The 'MyRoot' element is not declared."
What could be wrong?
In your MyRoot element, you need to add the location of the XSD. I would also recommend defining the namespace (unless you have good reason not to).
<api:MyRoot xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:api='http://www.myserver.com/schema'
xsi:schemaLocation='http://www.myserver.com/schema http://www.myserver.com/schema/websuiterecord.xsd'>
</api:MyRoot>
This way, the validation tool knows where to find your XSD to validate your XML against.
The approach was correct, but the XSD was not infact being read. I corrected this and it worked as expected.
I have received a XSD schema MainSchema.XSD and also Common.Xsd schema.
In MainSchema.xsd i have a following line:
<xs:include schemaLocation="Common.xsd"/>
And Common.Xsd hold a definition for various types of data like:
<xs:simpleType name="SSN">
<xs:annotation>
<xs:documentation>Social security number is 10 digits</xs:documentation>
<xs:appinfo>
<altova:exampleValues>
<altova:example value="5412983209"/>
<altova:example value=""/>
</altova:exampleValues>
</xs:appinfo>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
<xs:pattern value="([0-9]{10})?"/>
</xs:restriction>
</xs:simpleType>
and in MainSchema i have a property called SSNField of type SSN:
<xs:attribute name="CompanySSN" type="SSN">
<xs:annotation>
<xs:documentation>SSN number of Company</xs:documentation>
</xs:annotation>
</xs:attribute>
When i create a c# object class with this command:
xsd.exe -c -l:c# MainSchema.xsd Common.Xsd
it then created a object called:
MainSchema_Common.cs
When i validate an object against this Schema it comes up with an Exception:
{"Type 'http://schemas.domain.com:SSN' is not declared, or is not a simple type."}
Does anyone knows what i´m doing wrong ?
Bear in mynd that i received this XSD schemas from a outside source and i was told that there were no errors in this files.
Sincerly
agh
You need to explain how you are validating. I assume you are creating an instance of the class and then serializing to XML, and the xml is not validating?
You need to be aware that just because your xml is the product of serializing a type derived using xsd.exe does not automatically mean the xml will be compliant to the schema.
You may need to prime the XmlSerializer by injecting an override for the root namespace or indeed other nodes in the document.
For example to inject a namespace at a certain node:
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
var elementAttribute = new XmlElementAttribute(typeof(SSN))
{
ElementName = "SSN",
Namespace = "http://schemas.domain.com:SSN"
};
var newAttribute = new XmlAttributes();
newAttribute.XmlElements.Add(elementAttribute);
overrides.Add(typeof(ParentNodeType), "SSN", newAttribute);
To call the serilaizer:
XmlSerializer serializer = new XmlSerializer(typeof(MyType), overrides);
Hope this helps
What are the options to generate .NET 4.0 c# classes (entities) from an xsd file, using Visual Studio 2010?
simple enough; just run (at the vs command prompt)
xsd your.xsd /classes
(which will create your.cs). Note, however, that most of the intrinsic options here haven't changed much since 2.0
For the options, use xsd /? or see MSDN; for example /enableDataBinding can be useful.
xsd.exe as mentioned by Marc Gravell. The fastest way to get up and running IMO.
Or if you need more flexibility/options :
xsd2code VS add-in (Codeplex)
I show you here the easiest way using Vs2017 and Vs2019
Open your xsd with Visual Studio and generate a sample xml file as in the url suggested.
Once you opened your xsd in design view as below, click on xml schema explorer
2.
Within “XML Schema Explorer” scroll all the way down to find the root/data node. Right click on root/data node and it will show “Generate Sample XML”. If it does not show, it means you are not on the data element node but you are on any of the data definition node.
Copy your generated Xml into the clipboard
Create a new empty class in your solution and delete the class definition. Only Namespace should remain
While your mouse pointer focused inside your class, choose EDIT-> Paste Special-> Paste Xml as Classes
For a quick and lazy solution, (and not using VS at all) try these online converters:
xsd-to-xml-converter here
xmltocsharp converter here
XSD => XML => C# classes
Example XSD:
<?xml version="1.0" encoding="UTF-8" ?>
<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>
Converts to XML:
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid Technologies Online Tools 1.0 (https://www.liquid-technologies.com) -->
<shiporder xsi:noNamespaceSchemaLocation="schema.xsd" orderid="string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<orderperson>string</orderperson>
<shipto>
<name>string</name>
<address>string</address>
<city>string</city>
<country>string</country>
</shipto>
<item>
<title>string</title>
<note>string</note>
<quantity>3229484693</quantity>
<price>-6894.465094196054907</price>
</item>
<item>
<title>string</title>
<note>string</note>
<quantity>2181272155</quantity>
<price>-2645.585094196054907</price>
</item>
<item>
<title>string</title>
<note>string</note>
<quantity>2485046602</quantity>
<price>4023.034905803945093</price>
</item>
<item>
<title>string</title>
<note>string</note>
<quantity>1342091380</quantity>
<price>-810.825094196054907</price>
</item>
</shiporder>
Which converts to this class structure:
/*
Licensed under the Apache License, Version 2.0
http://www.apache.org/licenses/LICENSE-2.0
*/
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
[XmlRoot(ElementName="shipto")]
public class Shipto {
[XmlElement(ElementName="name")]
public string Name { get; set; }
[XmlElement(ElementName="address")]
public string Address { get; set; }
[XmlElement(ElementName="city")]
public string City { get; set; }
[XmlElement(ElementName="country")]
public string Country { get; set; }
}
[XmlRoot(ElementName="item")]
public class Item {
[XmlElement(ElementName="title")]
public string Title { get; set; }
[XmlElement(ElementName="note")]
public string Note { get; set; }
[XmlElement(ElementName="quantity")]
public string Quantity { get; set; }
[XmlElement(ElementName="price")]
public string Price { get; set; }
}
[XmlRoot(ElementName="shiporder")]
public class Shiporder {
[XmlElement(ElementName="orderperson")]
public string Orderperson { get; set; }
[XmlElement(ElementName="shipto")]
public Shipto Shipto { get; set; }
[XmlElement(ElementName="item")]
public List<Item> Item { get; set; }
[XmlAttribute(AttributeName="noNamespaceSchemaLocation", Namespace="http://www.w3.org/2001/XMLSchema-instance")]
public string NoNamespaceSchemaLocation { get; set; }
[XmlAttribute(AttributeName="orderid")]
public string Orderid { get; set; }
[XmlAttribute(AttributeName="xsi", Namespace="http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
}
}
Attention! Take in account that this is just to Get-You-Started, the results obviously need refinements!
xsd.exe does not work well when you have circular references (ie a type can own an element of its own type directly or indirectly).
When circular references exist, I use Xsd2Code. Xsd2Code handles circular references well and works within the VS IDE, which is a big plus. It also has a lot of features you can use like generating the serialization/deserialization code. Make sure you turn on the GenerateXMLAttributes if you are generating serialization though (otherwise you'll get exceptions for ordering if not defined on all elements).
Neither works well with the choice feature. you'll end up with lists/collections of object instead of the type you want. I'd recommend avoiding choice in your xsd if possible as this does not serialize/deserialize well into a strongly typed class. If you don't care about this, though, then it's not a problem.
The any feature in xsd2code deserializes as System.Xml.XmlElement which I find really convenient but may be an issue if you want strong typed objects. I often use any when allowing custom config data, so an XmlElement is convenient to pass to another XML deserializer that is custom defined elsewhere.
I use XSD in a batch script to generate .xsd file and classes from XML directly :
set XmlFilename=Your__Xml__Here
set WorkingFolder=Your__Xml__Path_Here
set XmlExtension=.xml
set XsdExtension=.xsd
set XSD="C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1\Tools\xsd.exe"
set XmlFilePath=%WorkingFolder%%XmlFilename%%XmlExtension%
set XsdFilePath=%WorkingFolder%%XmlFilename%%XsdExtension%
%XSD% %XmlFilePath% /out:%WorkingFolder%
%XSD% %XsdFilePath% /c /out:%WorkingFolder%
The command that worked in my case was:
xsd /c your.xsd
If you want to generate the class with auto properties, convert the XSD to XML using this then convert the XML to JSON using this and copy to clipboard the result.
Then in VS, inside the file where your class will be created, go to Edit>Paste Special>Paste JSON as classes.
I used xsd.exe in the Windows command prompt.
However, since my xml referenced several online xml's (in my case http://www.w3.org/1999/xlink.xsd which references http://www.w3.org/2001/xml.xsd) I had to also download those schematics, put them in the same directory as my xsd, and then list those files in the command:
"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\xsd.exe" /classes /language:CS your.xsd xlink.xsd xml.xsd
Marc Gravells answer was right for me but my xsd was with extension of .xml. When I used xsd program it gave :
- The table (Amt) cannot be the child table to itself in nested relations.
As per this KB325695 I renamed extension from .xml to .xsd and it worked fine.
Along with WSDL, I had xsd files. The above did not work in my case gave error. It worked as follows
wsdl /l:C# /out:D:\FileName.cs D:\NameApi\wsdl_1_1\RESAdapterService.wsdl
D:\CXTypes.xsd D:\CTypes.xsd
D:\Preferences.xsd