I want to read XSD File. But unable to find a proper way to parse XSD file.
<xsd:group name="group_name">
<xsd:annotation>
<xsd:documentation>Some text is here</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element minOccurs="0" name="Element_1" type="string">
<xsd:annotation>
<xsd:documentation>Some text is here</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element minOccurs="0" name="Element_2" type="string">
<xsd:annotation>
<xsd:documentation>Some text is here</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:group>
I want to read each group in my file, a sequence in that group and element in that sequence. And also need to read annotation of each group, I can element.
How can I do that?
XSD File are XML file, so you can read ot using XML parser such as LINQ which is a query to read data from data source, the link bellow is a good source about it:
https://msdn.microsoft.com/en-us/library/bb397933.aspx
So, the first step is to load the xml file then read it by LINQ query
Related
I have one XSD file as below:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:gml="http://www.opengis.net/gml" xmlns:njdot="SomeURL" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="SomeURL">
<xsd:import namespace="http://www.opengis.net/gml" schemaLocation="SomeURL/feature.xsd"/>
<xsd:complexType name="StudentType">
<xsd:complexContent>
<xsd:extension base="gml:AbstractfeatureType">
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="StudentId" nillable="false" type="xsd:decimal"/>
<xsd:element maxOccurs="1" minOccurs="1" name="class_ID" nillable="false" type="xsd:decimal"/>
<xsd:element maxOccurs="1" minOccurs="1" name="Name" nillable="false" type="xsd:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="Student" substitutionGroup="gml:_Feature" type="njdot:StudentType"/>
</xsd:schema>
My requirement is : Read this XSD data into c# on flying and Print them to console.
Currently while compiling XSD, I am getting following error:
Undefined complexType 'http://www.opengis.net/gml:AbstractFeatureType' is used as a base for complex type extension.
Error: Reference to undeclared substitution group affiliation.
I think I am not importing the external schema which is given with
Can anyone suggest what can be the solution or how can I achieve my desired output?
Thanks in advance.
If an attribute that is defined as an enumerated list is missing from an XML element should the first value in the list be used as a default if it doesn't have a default specified?
I have the following in a schema:
<xsd:simpleType name="YesNoType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="yes"/>
<xsd:enumeration value="no"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="TelephoneStructure">
<xsd:sequence>
<xsd:element name="TelNationalNumber" type="core:TelephoneNumberType"/>
<xsd:element name="TelExtensionNumber" type="core:TelephoneExtensionType" minOccurs="0"/>
<xsd:element name="TelCountryCode" type="core:TelCountryCodeType" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="TelUse" type="core:WorkHomeType"/>
<xsd:attribute name="TelMobile" type="core:YesNoType"/>
<xsd:attribute name="TelPreferred" type="core:YesNoType"/>
</xsd:complexType>
I have generated C# types from the above schema. I expected that missing attributes would result in null values, but I find that missing attributes default to the first value in the list, is this correct according to the XML spec?
Only TelExtensionNumber and TelCountry code are optional according to your schema. Everthing else is not optional, and so will assume the default value (0 for int, null for classes).
How to make an element in XML schema optional?
I have TCX exercise files which are written using the schema at https://www8.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd. I have been using them for years with Java and JAXB. I am trying to write a C# application to do the same thing. It is not going well. I can generate C# classes using xsd.exe as provided by Visual Studio. However, they do not make sense to me and cannot be used to deserialize my TCX files.
The basic structure of TCX files (at least the part in which I am interested) is they have a number of Activities containing a number of Laps containing a number of Tracks containing a number of Trackpoints. The Trackpoints have latitude, longitude, and heart rate as the main items of interest.
The xsd-generated C# classes have an Activity_t[], an ActivityLap_t[], and a Trackpoint_t[][]. There is no Track_t[] and the string Track_t does not appear in the file even though it is in the .xsd, for example in this excerpt for the Lap and Track.
<xsd:complexType name="ActivityLap_t">
<xsd:sequence>
<xsd:element name="TotalTimeSeconds" type="xsd:double"/>
<xsd:element name="DistanceMeters" type="xsd:double"/>
<xsd:element name="MaximumSpeed" type="xsd:double" minOccurs="0"/>
<xsd:element name="Calories" type="xsd:unsignedShort"/>
<xsd:element name="AverageHeartRateBpm" type="HeartRateInBeatsPerMinute_t" minOccurs="0"/>
<xsd:element name="MaximumHeartRateBpm" type="HeartRateInBeatsPerMinute_t" minOccurs="0"/>
<xsd:element name="Intensity" type="Intensity_t"/>
<xsd:element name="Cadence" type="CadenceValue_t" minOccurs="0"/>
<xsd:element name="TriggerMethod" type="TriggerMethod_t"/>
<xsd:element name="Track" type="Track_t" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Notes" type="xsd:string" minOccurs="0"/>
<xsd:element name="Extensions" type="Extensions_t" minOccurs="0">
<xsd:annotation>
<xsd:documentation>You can extend Training Center by adding your own elements from another schema here.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="StartTime" type="xsd:dateTime" use="required"/>
</xsd:complexType>
<xsd:complexType name="Track_t">
<xsd:sequence>
<xsd:element name="Trackpoint" type="Trackpoint_t" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
I don't understand how to deal with the [][] nor why it would be generated. And as mentioned it fails to parse.
error CS0030: Cannot convert type
'TrainingCenterDatabaseV2.Trackpoint_t[] to
TrainingCenterDatabaseV2.Trackpoint_t.
(The namespace I used is TrainingCenterDatabaseV2.)
This is the code used to deserialize:
private const string NS_TrainingCenterDatabase_v2 = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2";
XmlSerializer xmlSerializer = new XmlSerializer(typeof(TrainingCenterDatabase_t),
NS_TrainingCenterDatabase_v2);
FileStream fs = new FileStream(fileName, FileMode.Open);
XmlReader reader = XmlReader.Create(fs);
TrainingCenterDatabase_t tcx = (TrainingCenterDatabase_t)xmlSerializer.Deserialize(reader);
Not knowing where to go with this I tried the Visual Studio plugin, xsd2code++. This generates sensible C# classes with List<Activity_t>, List<ActivityLap_t>, and List<Trackpoint_t>. It also does not have Track_t, which seems to be somewhat superfluous.
However, it also fails to parse. I believe the problems here have to do with the lack of annotations it generates, compared to the ones generated from xsd.exe. I believe the problem is that it cannot handle the namespaces without those annotations, but I have seen no way to set options to get around that. As stated, I am not experienced with deserialization in C#. For my current purposes I have implemented reading the TCX files using XDocument rather than deserialization. However, I am curious as to why what I tried did not work, especially since xsd.exe has been around for a long time.
Thanks in advance.
This appears to be a bug with the xsd.exe tool itself. I would recommend using LinqToXsd (requires .NET Core 2.1), which is another Microsoft-developed technology for accessing XML data using an XSD; it's also more advanced than xsd.exe and in my quick testing appears to fully handle the above Garmin training center database schema without issue.
Also if you cannot install .NET Core on your machine, you can use this nuget package instead. The .NET Core version requires .NET Core 2.1 to actually generate code, but that generated code that can be used in an app that targets .NET Framework 4.6.2 and above.
I'm trying to read an XML file and validate against the schema specified by that file. I will not know the schema's location ahead of time, so I need to use the schema specified by the xml file.
Here's the relevant code (inspired by this answer):
var settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationFailed);
//settings.Schemas.Add("http://www.publishing.org", new XmlTextReader(#"C:\path\to\schema\Book.xsd"));
validatingReader = XmlReader.Create(xmlInputReader, settings);
while (validatingReader.Read()) ;
If I uncomment the settings.Schemas.Add line and comment the settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation out, everything works. I have also tested both the schema and the XML against an external validator.
The event handler message reports "Cannot load the schema for the namespace 'http://www.publishing.org' - Specified argument was out of the range of valid values. Parameter name: baseUri." and it occurs on line 2 (at the root element), followed by "Could not find schema information for the element 'http://www.publishing.org:[each element]'.
My first thought (and still the only thing I know it can be) was that the URI wasn't pointing to the xsd, but I've used 1) A full path via file:///C:\path\to\schema\Book.xsd, 2) A URI relative to the xml file, and 3) A URI relative to the application's current directory. The Visual Studio XML editor has no problem with any of these, but the XmlReader can't seem to find any of them.
Here's a simple schema and an xml instance (my actual schema is more complex, but this fails too):
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.publishing.org" xmlns="http://www.publishing.org"
version="1.0" elementFormDefault="qualified">
<xsd:element name="Book" type="BookType"/>
<xsd:complexType name="BookType">
<xsd:sequence>
<xsd:element name="Title" type="xsd:string" minOccurs="1" maxOccurs="1"/>
<xsd:element name="Author" type="xsd:string" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="Date" type="xsd:string" minOccurs="1" maxOccurs="1"/>
<xsd:element name="ISBN" type="xsd:string" minOccurs="1" maxOccurs="1"/>
<xsd:element name="Publisher" type="xsd:string" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<Book xmlns="http://www.publishing.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.publishing.org ../etc/Book.xsd">
<!-- Book.xsd file:///C:\path\to\schema\Book.xsd -->
<Title>Historic Doubts Relative to Napoleon Bonaparte</Title>
<Author>Richard Whately</Author>
<Author>Whately, Richard</Author>
<Date>1849</Date>
<ISBN>1465554777</ISBN>
<Publisher>Warren P. Draper</Publisher>
</Book>
I think everything is correct concerning my namespaces. I have also tried loading through an XmlDocument, but I get the same results. It has to be a problem locating the XSD, right?
I agree it should be a path problem.
I was able to use your code ( and the example you used :) ) .
I tested the validation against a local copy of the xsd, in a file, by setting my local file path inside the xml.
It did nothing when I used your exact xml, and indeed threw the validation error if I changed a tag.
My xsi:schemaLocation looks like:
xsi:schemaLocation="http://www.publishing.org C:\Users\Mike\Desktop\xml_test_files\test.xsd"
Did you try that simple local folder path?
I'm implementing a C# web service that is supposed to accept a custom message including unbounded number of elements.
Originally, the object is defined in a XSD file like below:
<xsd:element name="LogMessage">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="1" maxOccurs="1" name="avantlog" type="tns:LogEventType">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="LogEventType">
<xsd:sequence>
<xsd:element minOccurs="1" maxOccurs="1" name="context" type="tns:ContextType">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ContextType">
<xsd:sequence>
<xsd:element minOccurs="1" maxOccurs="unbounded" name="severity" type="xsd:string">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
And, in a CS file implementing the web service, I prepared a struct for this:
public struct logevent
{
public ContextType context;
public struct ContextType
{
public string[] severity;
}
}
However, when I tried to access an element of the 'serverity' using a line,
String temp = logevent.context.severity.GetValue(0).ToString()
, the program throws a following error:
"Index was outside the bounds of the array."
When I changed the element from 'unbounded' to '1' in the XSD file and also modified 'public string[] severity;' to 'public string severity;', it works.
Can anyone help me to make the web service to accept a message including unbounded numbers of elements?
The code that corresponds to specified XSD (if serialized using XmlSerializer) is the following:
[XmlRoot("LogMessage"]
public class LogMessage
{
[XmlElement("avantlog")]
public LogEventType AvantLog {get; set;}
}
public class LogEventType
{
[XmlArray("context")]
[XmlArrayItem("severity")]
public string[] Severity {get; set;}
}
You may have to use attributes in order to control the deserialization of the incoming XML. By default, the supported XML structure for arrays follows the form:
<Elements>
<Element>X</Element>
<Element>Y</Element>
</Element>
However, your WSDL specifies unbounded "Element" terms and does not provide for a parent "Elements" block. My understanding is that in order to use unbounded terms, you need to specify attributes to control the deserialization, as unbounded terms are not the default in .NET WSDL generation and deserialization.
This article discusses how to control deserialization using attributes:
http://msdn.microsoft.com/en-us/library/2baksw0z.aspx
You can convert your XSD to a POCO object using "XSD.exe" and then use XmlSerializer. This will make it easy to interact with multiple external systems via XML. Might want to use SGen.exe as well to increase XmlSerializer Performance. Hope this Helps
http://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.71).aspx
http://www.jonasjohn.de/snippets/csharp/xmlserializer-example.htm