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.
Related
I have learned a lot from reading in this forum, but today I need to ask a question.
I am working on my own XML Author Editor, which will later be used to create instructions as XML documents. I am using AvalonEdit (C#/WPF) as the basis for the editor.
I already have an XML schema for validation. It is structured in such a way that each defined element (along with its attributes) is located at the top level directly under "xsd:schema" (see example).
Each of these elements has sub-elements that are included either as xsd:choice or xsd:sequence with "ref attributes". A referenced sub-element is always an upper level element.
This allows elements to be validly nested in the XML document while respecting the schema.
My question now would be:
Suppose the cursor is behind the element "<emphasis>Text Emphasis</emphasis>" in my XML document. How can I filter out the elements in the schema which can be validly inserted at the cursor position?
After all, it may be that some elements with the allowed number are already inserted, and thus only certain elements can be validly inserted.
My question is not only fixed on this example, but a general approach should be found.
I see the problem in the many possibilities XML Schema offers: Querying "complexType", "sequence", "minOccurs", maxOccurs" including their nestings seems to me a very big and error-prone effort.
Does anyone know an approach how I could proceed? Or can someone point me to projects or sites where I might find information?
XMetal, for example, provides a method "CanInsertList" in its paid XML editor API with the description "You can insert any element listed into the current selection". I have tested this successfully with a trial version. So there must be a way.
XML-SCHEMA
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="paragraph">
<xsd:complexType mixed="true">>
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:choice minOccurs="1" maxOccurs="2">
<xsd:element ref="halfsided" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="emphasis" minOccurs="0" maxOccurs="1"/>
<xsd:element ref="quotationmarks" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:element ref="numericallist" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element ref="info" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" use="required"/>
<xsd:attribute name="creator" default="Employees1">
</xsd:complexType>
</xsd:element>
<xsd:element name="numericallist">
...
XML-Document
<section>
<paragraph id="123">Text 1
<emphasis>Text Emphasis</emphasis>
<quotationmarks>Text Quotationmarks</quotationmarks>
Text 2
</paragraph>
</section>
You need access to a compiled form of the schema. For example, if you compiled the schema using Saxon-EE, you could export an SCM file containing the compiled schema, which includes an XML representation of the finite state automaton for validating complex types. With the FSA, you can determine what the valid transitions are from any given state, and you can use this for schema-aware editing.
first of all thank you very much for your answer!
Michael, your suggestion to create a SCM file with Saxon-EE, which gives me useful data, sounds very good. There I also trust you without a doubt.
Unfortunately I don't have a Saxon-EE version yet to follow this. Of course I'm willing to invest in such a version if it helps me.
But I would like to have a look at a small Test.xsd with compiled Test.scm before, to see how I can build on it.
Is it possible to find such an example somewhere on the net, or could someone provide me with something like that?
That would be very helpful for sure.
Many greetings
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 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.
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.
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.