I am comparing two XMLs based on the same XMLSchema.
Every Element within the XML has an id (id says nothing about the order - the oldest xmlElement has the lowest id and so on).
My goal would be to get sort of an alignment between the two XMLS.
To give a very simple example.
Let there be two xmls. The first one looks like this:
<EleType>
<Ele id="1"/>
<Name id="2"/>
<Description id="100"/>
<UnknownOrderEle1 id="3"/>
</EleType>
and the second one like this:
<EleType>
<Ele id="1"/>
<Name id="2"/>
<Description id="100"/>
<UnknownOrderEle2 id="4"/>
</EleType>
My result should be a mapping of ids.
It will start off nicely with 1:1, then 2:2, 100:100. At this moment I come across two xml elements with differing names. I know they may not be matched, so the two possible solutions would be to take 3:* (where * = symbol for no match) and then *:4 or to take :4 and then 3:.
BUT only one way is the correct solution because the schema says that UnknownOrderEle2 (id=4) should come before UnknownOrderEle1 (id=3.
So I looked for anything within the XmlSchema class, XmlSchemaInfo, XmlSchemaElement,... that tells me anything about the element order. The only two possibilities I found are no real solutions for me, since they are either too time consuming or unclean.
One would be to compare the LineNumber and LinePosition within the XmlSchemaObject (probably unclean).
The other one would be to construct an xml out of the two xmls and validate it. If it throws a validation exception I know that the order that I picked was wrong (definitely time consuming).
I would be glad to receive any help if anybody knows a better solution.
The schema corresponding to your example should contain something like this:
<xs:element name="EleType">
<xs:complexType>
<xs:sequence>
<xs:element name="Ele">
. . .
</xs:element>
<xs:element name="Name">
. . .
</xs:element>
<xs:element name="Description">
. . .
</xs:element>
<xs:element name="UnknownOrderEle1">
. . .
</xs:element>
<xs:element name="UnknownOrderEle2">
. . .
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Once loaded, you can get hold of the corresponding XmlSchemaElement object and then of the order of its sub-elements with some code like this:
XmlSchemaElement element = schema.Elements[new XmlQualifiedName("EleType")];
XmlSchemaType complexType = (XmlSchemaComplexType)element.ElementSchemaType;
XmlSchemaSequence sequence = (XmlSchemaSequence)complexType.Particle;
XmlSchemaObjectCollection childElements = sequence.Items;
childElements is the list of the valid sub-elements Ele, Name, Description, UnknownOrderEle1, UnknownOrderEle2, in the correct order.
This works as long as your schema is simple, but if the definition of the types are not simple sequences but more complex - with choice, groups and so on, it becomes much more complex, to the point that the other approach to create an XML file and try to validate it becomes probably better.
Related
I create a XML file in my application generated with the help with classes I created with XSD.exe from some schema files.
Now I was finally able to validate my XML against the schema and it tells me that some IDs I was using have the wrong format. I used C# GUIDs and the simpleType definition looks like this:
<xs:simpleType name="idDocument">
<xs:annotation>
...
</xs:annotation>
<xs:restriction base="xs:ID">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
I then searched for the definition of "xs:ID" and found one on: http://www.datypic.com/sc/xsd/t-xsd_ID.html which says:
Based on xsd:NCName
Pattern: [\i-[:]][\c-[:]]* (Defined in type xsd:NCName)
White Space: collapse (Defined in type xsd:token)
Some example IDs I have look like this:
_Q76m-TfmEeKLm53bgNs7IQ
_Q8qN1jfmEeKLm53bgNs7IQ
_3hVxYDfiEeKLm53bgNs7IQ
I don't like to reinvent the wheel and guess that maybe there is something already available in C# that lets me generate such an xml-ID that I can use. But so far I found nothing.
Does anybody know if such a thing already exists?
Is there a way to override the value of base complextypes value in XSD ?. To be more clear,
i have my base complex type as
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="Urn:commonBase"
elementFormDefault="qualified"
xmlns="Urn:commonBase"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="RequestBase">
<xs:attribute name="Version" default="1.0"/>
</xs:complexType>
</xs:schema>
and in another XSD and a different namespace i have
<xs:complexType name="Request">
<xs:complexContent>
<xs:extension base="base:RequestBase">
<xs:sequence>
<xs:element name ="FirstName"/>
</xs:sequence>
<xs:attribute name="Version" fixed="2.0"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
But when i generate the C# class file for the above using XSD.exe, a duplicate property is generated with the name "Version*1*" . i actually want an override facility in the class file which set the existing property of "RequestBase" from 1.0 to 2.0 and not a extra property. How to acheive this ?
Try using a restriction step to restrict the value of the 'Version' attribute from any simple type to '2.0', then an extension step to add the 'FirstName' element.
(Note that by fixing the value of 'Version' at '2.0' you make it impossible for anyone to base a version 3.0 type on your version 2.0 type in the way you're basing your 2.0 type on the 1.0 type. Do you really want to stick your thumb in the eye of the next guy in line that way?)
I am trying to validate an XML via an XSD in c# code. However it keeps throwing an XmlSchemaValidationException, namely "The 'refname' attribute is not declared.".
The code doing the validation:
XmlReaderSettings xmlSettings = new XmlReaderSettings();
xmlSettings.Schemas = new System.Xml.Schema.XmlSchemaSet();
xmlSettings.Schemas.Add(null, #"\\[Network-drive path]\KVSchemaMod.xsd");
xmlSettings.ValidationType = ValidationType.Schema;
xmlSettings.DtdProcessing = DtdProcessing.Parse;
xmlSettings.ValidationFlags = XmlSchemaValidationFlags.AllowXmlAttributes;
xmlSettings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema;
xmlSettings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
XmlReader reader = XmlReader.Create(#"\\[Network-drive path]\KV_Article.xml", xmlSettings);
// Parse the file.
while (reader.Read()) ;
The XSD (with repetitous parts removed):
<?xml version="1.0" encoding="iso-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:mapping-schema">
<xs:annotation>
<xs:appinfo>
<sql:relationship name="ProductIdentifier"
parent="tblKVProduct"
parent-key="record_reference"
child="tblKVProductIdentifier"
child-key="record_reference" />
... (More SQL-mappings)
<xs:element name="ONIXMessage" sql:is-constant="1">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Product" sql:relation="tblKVProduct">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="RecordReference" sql:field="record_reference" >
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
<xs:maxLength value="32"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
...(More elements under Product)
The XML to be validated (ONIX-standard):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ONIXMessage SYSTEM "http://www.editeur.org/onix/2.1/reference/onix- international.dtd">
<ONIXMessage>
<Product>
<RecordReference>0786606274</RecordReference>
<NotificationType>03</NotificationType>
<ProductIdentifier>
<ProductIDType>01</ProductIDType>
<IDTypeName>Kustantajan tuotenumero</IDTypeName>
<IDValue>95535</IDValue></ProductIdentifier>
<ProductIdentifier>
<ProductIDType>02</ProductIDType>
<IDValue>0786606274</IDValue></ProductIdentifier>
<ProductIdentifier>
<ProductIDType>03</ProductIDType>
<IDValue>9780786606276</IDValue>
</ProductIdentifier>
...(And more Product-fields)
The XML also has a Header tag as the first child of ONIXMessage (followed by all Product tags that as also childrens of ONIXMessage), but since none of the fields there are referenced in the schema I don't see how they could cause this particular error.
As I googled the error I read up on the XmlSchemaElement.RefName property (MSDN Definition) it even explicitly says that "The value cannot be set if the containing element is the schema element."
Since that is the case for the XSD I don't understand why it throws an error about it not being declared.
I've been trying to find out if this could be related to the lack of namespace, but in my mind that shouldn't be a problem since there is none in neither the XML nor the XSD. Or does one need to force a namespace onto the root-element in order to validate the XML?
The validating code does work with another set of XML/XSD (very different build-up on those though), could that just be a fluke though and the error actually in the way I validate?
Just for completion's sake, the Header tag in the XML:
<Header>
<FromCompany></FromCompany>
<FromPerson></FromPerson>
<FromEmail></FromEmail>
<AddresseeIdentifier>
<AddresseeIDType></AddresseeIDType>
<IDTypeName></IDTypeName>
<IDValue></IDValue>
</AddresseeIdentifier>
<ToCompany></ToCompany>
<ToPerson></ToPerson>
<MessageNumber></MessageNumber>
<SentDate></SentDate>
<MessageNote></MessageNote>
</Header>
It's not possible to reproduce your problem, given that you haven't provided a complete example. If you want answers based on anything other than speculation, you need to cut down your schema and your data to the smallest example that illustrates the problem, so question answerers can reproduce the problem and study it in more detail. It will often happen, of course, that your problem dissolves in the process because you come to see what's going wrong in the process of finding a small example of the problem. But that's just a risk you have to take.
That said, however, I'll go ahead and speculate. The RefName property on the XMLSchemaElement object is almost certainly a red herring. The message makes it sound much more as if the XML you are attempting to validate has an attribute named refname somewhere (in the bit you elided), and your XSD schema has no definition for it. Certainly the XSD fragment you provide has no definition for it.
The vocabulary defined at http://www.editeur.org/onix/2.1/reference/onix-international.dtd (which you point to in your XML), however, does define refname as an attribute on many elements (probably all of them, though I haven't checked each one individually). So it's not at all implausible that an ONIXMessage element might contain a descendant with a refname attribute.
Actually, it's not just not implausible; it's certain.
The DTD pointed to by your XML supplies a default value for the refname attribute on all elements (at least, all the ones I've seen), for which your XSD schema declaration appears not to be prepared. That is, the first start-tag of your document seen by the schema validator is not <ONIXMessage> but <ONIXMessage refname="ONIXMessage" shortname="ONIXmessage">.
If you're not using the XSD available from www.editeur.org, the simplest way forward is probably to reconsider that decision and use the schema from editeur.org instead of rolling your own. It includes declarations for the refname and shortname attributes. If you are using that schema, or rather trying to use it, something has gone badly wrong and your validator is not finding or reading it. In that case, your best way forward is to figure out why your system is not finding the correct schema documents.
There is something fundemental I don't understand about Xml Schema declarations. I have the following declaration in an .xsd file:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="tile">
<xs:restriction base="xs:string">
<xs:pattern value="[a-z][0-9]"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="move">
<xs:complexType>
<xs:sequence>
<xs:element name="T" type="tile" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
So, for example <move><T>a0</T><T>v5</T></move> should be a valid XML element according to the xsd file. (I've simplified the actual declaration, so the move may not make sense)
Background: I am developing a project in C# 4.0. I use this xsd file as a project source. When I receive an XElement from somewhere, I first check whether it is valid according to the xsd above. The C# code works OK.
Here is my question (hopefully a single question, asked three times):
1) I want to put my declarations on a domain. Let's say aliferhat.com. Or do I want to? Why should I want to do that? How can I do that? How can I use that declaration later from somewhere else?
2) I will have many similar xsd files. Most of them will use the "tile" definition, so I want to put the part "tile" on a seperate file, and refer to that file from other xsd files. How can I do that? How will the system know where to look for definitions?
3) This is what the visual studio generates when I add a new XSD file to the project:
<xs:schema id="temp"
targetNamespace="http://tempuri.org/temp.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/temp.xsd"
xmlns:mstns="http://tempuri.org/temp.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
</xs:schema>
What does xmlns:xs and targetNamespace attributes do? Are xs:element and the rest really defined in one of these URIs? Do the C# compiler really look up those URIs for the definitions?
I hope and guess I have asked only one question. I've read the "XML schema definition" page on W3 schools but could not find the answer. Any help will be appreciated.
I have a sequence with an allowed minimum length of zero in my xsd. When I try and load an xml file which doesn't have any elements of the sequence into the DataSet that xsd.exe created I get an exception indicating that my file violated one of the DataSet's constraints. The xml file validates against the schema so I know it's valid. Is there anything I can do to make the tool generate a valid dataset?
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Numbers" type="xs:double"/>
</xs:sequence>
Edit: if I change my schema to this the generated code works properly. It looks wrong to me though since it appears to be implying that I could have sequence items with nothing in them, which doesn't make any sense.
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Numbers" type="xs:double" minOccurs="0"/>
</xs:sequence>
This sounds like it is because of the way that xsd.exe handles minOccurs and maxOccurs. This MSDN article describes the way that xsd.exe handles minOccurs / maxOccurs. This section of that article seems to tally with your initial problem:
A loss of definition precision occurs
when Xsd.exe ignores the minOccurs
attribute in the case when the
maxOccurs attribute value dictates an
array binding. A reverse translation
from the generated array to a new
declaration produces not the
original minOccurs value but a value
of 0, plus a maxOccurs value of
unbounded.