I created XSD using Visual StudioXML Tools. And I use following C# code to validate XML and facing this error.
Error
The element is not declared
'http://www.w3.org/2000/09/xmldsig#:Signature'.
So my question is how to fix it because in edit mode XML is valid 100%?
Thank you!
C#
private void buttonValidateXML_Click(object sender, EventArgs e)
{
try
{
bool result = IsValidXml2(textBoxSignedXML.Text, textBoxXSDFile.Text, "");
rtbValidationResult.Text = result.ToString();
}
catch (Exception ex)
{
rtbValidationResult.Text = ex.Message;
}
}
public static bool IsValidXml2(string xmlFilePath, string xsdFilePath, string namespaceName)
{
var xdoc = XDocument.Load(xmlFilePath);
var schemas = new XmlSchemaSet();
schemas.Add(namespaceName, xsdFilePath);
bool result = true;
xdoc.Validate(schemas, (sender, e) =>
{
result = false;
});
return result;
}
XML
<?xml version="1.0" encoding="utf-8"?>
<Envelope version="1">
<Deposit>
<ClientId>1234567890123</ClientId>
<Account>0045678</Account>
<Currency>USD</Currency>
<Total>5000.00</Total>
<SignedDate>2016-02-15</SignedDate>
<Cheques>
<Cheque>
<Images>
<Front>
SUkqAAgAAAAPAP4ABAABAAAAAAAAAAABBAABAAAAfQUAAAEBBAABAAAAWgIAAAIBAwABAAAAAQAA
AAMBAwABAAAABAAAAAYBAwABAAAAAAAAAA4BAgAhAAAA0AAAABEBBAABAAAAAAIAABIBAwABAAAA
AQAAABUBAwABAAAAAQAAABYBBAABAAAAWgIAABcBBAABAAAAvi8AABoBBQABAAAAAAEAABsBBQAB
EdF0fRG0R0YRdH2R2XzaI6OxRQAQAQA=
</Front>
<Back>
SUkqAAgAAAAOAP4ABAABAAAAAAAAAAABBAABAAAAgQUAAAEBBAABAAAAVAIAAAIBAwABAAAAAQAA
AAMBAwABAAAABAAAAAYBAwABAAAAAAAAABEBBAABAAAAAAEAABIBAwABAAAAAQAAABUBAwABAAAA
AQAAABYBBAABAAAAVAIAABcBBAABAAAAcggAABoBBQABAAAAwAAAABsBBQABAAAA0AAAACgBAwAB
AAAAAgAAAAAAAAAAAAAAAAAAAAAAyAAAAAEAAAAAAAAAAAAAAMgAAAABAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//LZCdO1f7iRrKXTqt//pePx///9lNoL487Ajh
jFyzUrtwg+6gg9VmvCIWA42XMwziSUEEw7GoIcSUWZ3Y0oKmGR3LToGVC2LhkK6H4sorQNRUMLjH
LTGzlpv3RFCcH4NLB9hvLTmD8tMgOsG+WVaR5AweTcEWMMfaDQxDIx5NwVQx8OMPeGFHLSUlLcSS
1JtNV/9/rrffuO+h9bx////kfvABABAA
</Back>
</Images>
<MicrCodeCmc>123456789012345678901234567890</MicrCodeCmc>
<Amount>465.22</Amount>
<PaymentDate>2016-02-15</PaymentDate>
<EmissionDate>2016-02-15</EmissionDate>
</Cheque>
<Cheque>
<Images>
<Front>
SUkqAAgAAAAPAP4ABAABAAAAAAAAAAABBAABAAAAfQUAAAEBBAABAAAAWgIAAAIBAwABAAAAAQAA
AAMBAwABAAAABAAAAAYBAwABAAAAAAAAAA4BAgAhAAAA0AAAABEBBAABAAAAAAIAABIBAwABAAAA
AQAAABUBAwABAAAAAQAAABYBBAABAAAAWgIAABcBBAABAAAAvi8AABoBBQABAAAAAAEAABsBBQAB
EdF0fRG0R0YRdH2R2XzaI6OxRQAQAQA=
</Front>
<Back>
SUkqAAgAAAAOAP4ABAABAAAAAAAAAAABBAABAAAAgQUAAAEBBAABAAAAVAIAAAIBAwABAAAAAQAA
AAMBAwABAAAABAAAAAYBAwABAAAAAAAAABEBBAABAAAAAAEAABIBAwABAAAAAQAAABUBAwABAAAA
AQAAABYBBAABAAAAVAIAABcBBAABAAAAcggAABoBBQABAAAAwAAAABsBBQABAAAA0AAAACgBAwAB
AAAAAgAAAAAAAAAAAAAAAAAAAAAAyAAAAAEAAAAAAAAAAAAAAMgAAAABAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//LZCdO1f7iRrKXTqt//pePx///9lNoL487Ajh
jFyzUrtwg+6gg9VmvCIWA42XMwziSUEEw7GoIcSUWZ3Y0oKmGR3LToGVC2LhkK6H4sorQNRUMLjH
LTGzlpv3RFCcH4NLB9hvLTmD8tMgOsG+WVaR5AweTcEWMMfaDQxDIx5NwVQx8OMPeGFHLSUlLcSS
1JtNV/9/rrffuO+h9bx////kfvABABAA
</Back>
</Images>
<MicrCodeCmc>123456789012345678901234567890</MicrCodeCmc>
<Amount>99999999999</Amount>
<PaymentDate>2016-02-15</PaymentDate>
<EmissionDate>2016-02-15</EmissionDate>
</Cheque>
</Cheques>
</Deposit>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>TVO2Gssf5TUdXFYG/PrHDyqYFqs=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>KwQInN03ywa0u0t4HedxgE1fOU7XYLQScKuQ6vdYoIZME5Hm5jpFeX2ORA2U+BO7JNjmFilTW05VntS3k98YCZhNXH9Iw/YEC1nw4JJLzygYbbCftkiY5v5+b494mQPryCtscwTtbziW6QilILSFDGmco2JopRfVe+qfdN/JyB1HXhUfApyNEsw/cJLj6aaz5ivN1sLFgAlikbwCNpF+mRnZY5u7/S8uT8WhEyK32EcatdjzKbP0PwnIlumhOpUMerWeLZ7neuJq6R/IuFgZ1Y5U6ppyuOjhtiHp4glC/uNUS/y7jMzG29thWBkEtSE9AcEt2IZ0HOEZE3kdFXufjA==</SignatureValue>
</Signature>
</Envelope>
XSD
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.com/ct-required"
xmlns:xmime="http://www.w3.org/2005/05/xmlmime" >
<xs:import namespace="http://www.w3.org/2005/05/xmlmime"
schemaLocation="http://www.w3.org/2005/05/xmlmime"/>
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd"/>
<xs:simpleType name="PNGPictureType"
xmime:expectedContentTypes="image/png">
<xs:restriction base="xs:base64Binary"/>
</xs:simpleType>
<xs:simpleType name="Money">
<xs:restriction base="xs:decimal">
<xs:totalDigits value="13" />
<xs:fractionDigits value="2" />
<xs:minInclusive value="0.00" />
<xs:maxInclusive value="99999999999.99" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Currency">
<xs:annotation>
<xs:documentation>Currency Code: ISO 4217</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="USD" />
<xs:enumeration value="UYU" />
<xs:minLength value="3" />
<xs:maxLength value="3" />
</xs:restriction>
</xs:simpleType>
<xs:element name="Envelope">
<xs:complexType>
<xs:sequence>
<xs:element name="Deposit" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="ClientId" type="xs:unsignedLong" />
<xs:element name="Account" type="xs:unsignedLong" />
<xs:element name="Currency" type="Currency" />
<xs:element name="Total" type="Money" />
<xs:element name="SignedDate" type="xs:date" />
<xs:element name="Cheques">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Cheque">
<xs:complexType>
<xs:sequence>
<xs:element name="Images">
<xs:complexType>
<xs:sequence>
<xs:element name="Front" type="PNGPictureType" />
<xs:element name="Back" type="PNGPictureType" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="MicrCodeCmc" type="xs:string" />
<xs:element name="Amount" type="Money" />
<xs:element name="PaymentDate" type="xs:date" />
<xs:element name="EmissionDate" type="xs:date" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element xmlns:q1="http://www.w3.org/2000/09/xmldsig#" ref="q1:Signature" />
</xs:sequence>
<xs:attribute name="version" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
UPDATE #1
I have tried different approaches but no joy.
And even if I reference XSD to local file it does not work. I see the same error.
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212 file:///C:/Temp/xmldsig-core-schema.xsd"/>
UPDATE #2
Even I use this approach no joy.
public static bool IsValidXml1(string xmlFilePath, string xsdFilePath, string namespaceName)
{
XDocument xdoc = null;
var settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Ignore;
settings.ProhibitDtd = false;
try
{
using (XmlReader xr = XmlReader.Create(xmlFilePath, settings))
{
xdoc = XDocument.Load(xr);
var schemas = new XmlSchemaSet();
schemas.Add(namespaceName, xsdFilePath);
schemas.Add(#"http://www.w3.org/2000/09/xmldsig#", #"D:\Temp\xmldsig-core-schema.xsd");
xdoc.Validate(schemas, null);
return true;
}
}
catch (XmlSchemaValidationException ex)
{
// throw;
}
return false;
}
If you don't want to change anything to xsd or xml - do the following:
(optional) Download xsd from w3 site and save to local disk. W3 site is VERY slow because a lot of software worldwide constantly request those schemas. If you will use that xsd directly - you will often fail by timeout. Some validation tools already have such schemas cached locally, but not .NET validator.
Modify your validation method from UPDATE 2 the following way:
public static bool IsValidXml1(string xmlFilePath, string xsdFilePath, string namespaceName)
{
XDocument xdoc = null;
var settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Ignore;
try
{
using (XmlReader xr = XmlReader.Create(xmlFilePath, settings))
{
xdoc = XDocument.Load(xr);
var schemas = new XmlSchemaSet();
schemas.Add(namespaceName, xsdFilePath);
using (var fs = File.OpenRead(#"D:\Temp\xmldsig-core-schema.xsd"))
using (var reader = XmlReader.Create(fs, new XmlReaderSettings() {
DtdProcessing = DtdProcessing.Ignore // important
})) {
schemas.Add(#"http://www.w3.org/2000/09/xmldsig#", reader);
}
xdoc.Validate(schemas, null);
return true;
}
}
catch (XmlSchemaValidationException ex)
{
// throw;
}
return false;
}
You have to add that schema using XmlReader and not directly, because if you add directly (like in your update 2) - it will fail to parse DTD block, because when you add XmlSchema to XmlSchemaSet using url (or file path) - it will read that file using XmlReaderSettings with DtdProcessing = DtdProcessing.Prohibit. We need to change that to DtdProcessing.Ignore or DtdProcessing.Parse. After that your validation method will work fine for target xsd and xml file, without any changes (and will correctly fail in case xml does not match xsd).
You are very close. In your XSD, simply replace,
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" />
with
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation=
"http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd"/>
and your XSD will no longer have that error, and your XML will be valid against your XSD.
Explanation
XSDs can be composed via xs:import and xs:include. In both cases, the location of the referenced XSD has to be specified with a required schemaLocation attribute, which was missing in OP's original XSD. By adding xs:import/#schemaLocation as shown above, the error is eliminated.
Update #1:
When you switched to use a local XSD, you made a mistake in your xs:import:
Change
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212
file:///C:/Temp/xmldsig-core-schema.xsd"/>
to
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="file:///C:/Temp/xmldsig-core-schema.xsd"/>
(You were following an example for #xsi:schemaLocation in XML documents which has namespace-location pairs; xs:import/#schemaLocation is different.)
Update #2:
So my question is how to fix it because in edit mode XML is valid 100%?
Perhaps this is the disconnect. Editing an XML file in Visual Studio does not automatically validate it against an XSD. You need to do that in code or via a validating XML editor such Oxygen XML Editor or XML Spy.
Also, your C# validation code may have issues. See Validating an XML against referenced XSD in C#
Related
I have an xml schema file that describes an element called MessageProcessingResult that can have child elements 'MessageID' and 'Category'. My xml clearly has these elements yet when I validate the xml against the schema I get an error stating the 'Category' element is invalid:
The element 'MessageProcessingResult' in namespace
'http://test.com/MessageProcessing' has invalid child element
'Category' in namespace 'http://test.com/MessageProcessing'. List of
possible elements expected: 'Category, MessageID'.
I must be defining my schema incorrectly, but I don't know exactly what it is.
My schema, xml and validation code are as follows:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://test.com/MessageProcessing"
targetNamespace="http://test.com/MessageProcessing"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xs:element name="MessageProcessingResult">
<xs:complexType>
<xs:all>
<xs:element name="MessageID" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="Category">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Success"/>
<xs:enumeration value="Problem"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
xml that looks like this:
<MessageProcessingResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://test.com/MessageProcessing">
<Category>Success</Category>
<MessageID>id</MessageID>
</MessageProcessingResult>
I validate with this code:
public class XmlValidator
{
public void Validate(Stream strXml)
{
XmlReaderSettings settings = new XmlReaderSettings();
//settings.Schemas.Add(null, #"Schema\MessageProcessingResults.xsd");
settings.Schemas.Add(null, #"Schema\MessageProcessingResult.xsd");
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new ValidationEventHandler(XmlSchemaValidationEventHandler);
XmlReader xml = XmlReader.Create(strXml, settings);
this.Errors = new List<string>();
while (xml.Read()) { }
}
public List<string> Errors { get; set; }
private void XmlSchemaValidationEventHandler(object sender, ValidationEventArgs e)
{
this.Errors.Add($"{e.Severity} {e.Message}");
}
}
In your XSD, change
elementFormDefault="unqualified"
to
elementFormDefault="qualified"
Your explicit setting of elementFormDefault="unqualified" (which also happens to be the default setting) means that locally declared elements are in no namespace. This is undesired in your case (and rarely ever desired, in fact). For further details, see What does elementFormDefault do in XSD?
I am using Visual Studio 2015.
I apologize for the poorly named "firstName" element. It should have been "fullName", but since I already generated the class for the schema, and this is just for my own learning, I left it as is.
I have an XML schema here:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="address-schema"
targetNamespace="http://tempuri.org/address-schema.xsd"
elementFormDefault="qualified"
attributeFormDefault="qualified"
xmlns:addr="http://tempuri.org/address-schema.xsd"
xmlns:mstns="http://tempuri.org/address-schema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="address">
<xs:complexType>
<xs:sequence>
<xs:element name="firstName">
<xs:complexType>
<xs:sequence>
<xs:element name="first" type="addr:nameComponent"/>
<xs:element name="middle" type="addr:nameComponent" minOccurs="0"/>
<xs:element name="last" type="addr:nameComponent"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="nameComponent">
<xs:simpleContent>
<xs:extension base="xs:string"/>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
And an XML file that I think conforms to the schema:
<?xml version="1.0" encoding="utf-8" ?>
<addr:address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tempuri.org/address-schema.xsd address-schema.xsd"
xmlns:addr="http://tempuri.org/address-schema.xsd">
<addr:firstName>
<addr:first>Some</addr:first>
<addr:middle>Bodys</addr:middle>
<addr:last>Name</addr:last>
</addr:firstName>
</addr:address>
And the code that is attempting to validate the XML is here (note that the "address" class that the XML file is getting deserialized into is an auto generated class from xsd.exe):
address address;
var xmlSchemaSerializer = new XmlSerializer(typeof(XmlSchema));
var addressXmlSerializer = new XmlSerializer(typeof(address));
var schemas = new XmlSchemaSet();
XmlSchema schema;
using (var xsdStream = File.OpenRead("address-schema.xsd"))
{
schema = (XmlSchema)xmlSchemaSerializer.Deserialize(xsdStream);
}
schemas.Add(schema);
var settings = new XmlReaderSettings
{
Schemas = schemas,
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ReportValidationWarnings | XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation
};
settings.ValidationEventHandler += (sender, arguments) =>
{
throw new XmlSchemaValidationException(arguments.Message);
};
using(Stream addressXmlStream = File.OpenRead("address-doc.xml"))
using (XmlReader reader = XmlReader.Create(addressXmlStream, settings))
{
address = (address)addressXmlSerializer.Deserialize(reader);
}
Console.WriteLine(address.firstName.first.Value == "Some" ? "Success!" : "Fail");
Console.ReadKey();
The exception ('System.Xml.Schema.XmlSchemaValidationException'The global element 'http://tempuri.org/address-schema.xsd:address' has already been declared.) is thrown in the ValidationEventHandler.
Any help or suggestions would be appreciated. Thanks in advance!
The cause of your exception is that your document has a schema location hint that loads the schema, but you've already loaded it.
Either don't pre-load the schema or remove the xsi:schemaLocation attribute from your document.
I am building a web service in .NET that will pass data back and forth via XML. I would like to validate the XML in the incoming requests using an XSD that I have defined.
Here is the XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="POSearch">
<xs:sequence minOccurs="0" maxOccurs="10">
<xs:element name="POID" type="xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Here is the XML:
<POSearch>
<POID>1</POID>
<POID>2</POID>
</POSearch>
Here is the validation code in C#:
static void Main(string[] args){
XmlSchemaSet iSchemas = new XmlSchemaSet();
iSchemas.Add(string.Empty, #"...xsd file location");
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
settings.Schemas.Add(iSchemas);
XmlReader reader = XmlReader.Create(#"...xml file location", settings);
try {
while(reader.Read())
;
}
catch(Exception ex) {
Console.WriteLine(ex.Message);
}
}
private static void ValidationCallBack(object sender, ValidationEventArgs args) {
if(args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found. No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);
}
I feel like I had this working before and I'm not completely sure why this isn't working now. Whenever I run this I get the following Exception Message:
Validation error: The 'POSearch' element is not declared.
Have I defined my XSD wrong? Is my validation code wrong? The elements are all clearly there. Any help pointing me in the right direction is greatly appreciated.
You have the type declared but no element declared of that type.
Add an element declaration:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="POSearch" type="POSearch"/>
<xs:complexType name="POSearch">
<xs:sequence minOccurs="0" maxOccurs="10">
<xs:element name="POID" type="xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Try this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="POSearch">
<xs:sequence minOccurs="0" maxOccurs="10">
<xs:element name="POID" type="xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
<xs:element name="POSearch" type="POSearch"/>
</xs:schema>
I have 2 xsd files content in a dictionary. I want to merge both the contents and create one xsd file.
1st xsd content from dictionary has a import tag pointing to 2nd xsd in the dictionary.
1st xsd -
<?xml version="1.0" encoding="IBM437"?>
<xs:schema xmlns:tns="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/EnrichedMessageXML" targetNamespace="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/Enr
ichedMessageXML" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="COMP.EDI._00401._810.Schemas.Headers" namespace="http://EDI/Headers" />
<xs:element name="X12EnrichedMessage">
<xs:complexType>
<xs:sequence>
<xs:element xmlns:q1="http://EDI/Headers" ref="q1:Headers" />
<xs:element name="TransactionSet">
<xs:complexType>
<xs:sequence>
<xs:element xmlns:q2="http://schemas.microsoft.com/BizTalk/EDI/X12/2006" ref="q2:X12_00401_810" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
2nd sxd -
<?xml version="1.0" encoding="IBM437"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://EDI/Headers" xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://EDI/Headers">
<xs:element name="Headers">
// Some content here
</xs:element>
</xs:schema>
desired xsd I want is the merger of both the xsd documents.
I am following this : http://msdn.microsoft.com/en-us/library/ms256237%28v=vs.110%29.aspx article, I am able to add the schemas to schemaset object also, but when I am using RecurseExternals function (from the article) this is not showing the merged xsd but 2 different xsd.
my block of code -
XmlSchemaSet schemaSet = new XmlSchemaSet();
// This prevents schemaLocation and Namespace warnings
// at this point we already have the schema from schemaLocation.
//schemaSet.XmlResolver = null;
schemaSet.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
// add schema in schema set from schemacollection object
foreach (var item in schemaCollection)
{
schemaSet.Add(item.Key, new XmlTextReader(new StringReader(item.Value)));
}
schemaSet.Compile();
XmlSchema mainXmlSchema = null;
XmlSchemaImport import = new XmlSchemaImport();
foreach (XmlSchema sch in schemaSet.Schemas())
{
// pick the main schema from the schemaset to include
// other schemas in the collection.
if (sch.TargetNamespace == mainSchemaNS)
{
mainXmlSchema = sch;
}
else
{
import.Namespace = sch.TargetNamespace;
import.Schema = sch;
mainXmlSchema.Includes.Add(import);
}
}
schemaSet.Reprocess(mainXmlSchema);
schemaSet.Compile();
RecurseExternals(mainXmlSchema);
am I doing anything wrong ?
I'm trying to add the annotation element inside the xs:choice. According to the xs:choice syntax, this could be possible. I could not find the sample of choice with annotation inside BTW. My current version of xsd file contains an element:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.es.de/es3/flex/simple"
elementFormDefault="qualified"
xmlns="http://www.es.de/es3/flex/simple"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:flex="http://www.es.de/es3/flex/flexBase">
<xs:import namespace="http://www.es.de/es3/flex/flexBase" />
<xs:element name="ESS3754">
<xs:complexType>
<xs:choice>
<xs:annotation>
<xs:appinfo>
<flex:ControlHeadline>Headline_VVVVV</flex:ControlHeadline>
<flex:helpText>HelpText_VVVVV</flex:helpText>
</xs:appinfo>
</xs:annotation>
<xs:element name="String1" type="xs:string" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
However, while parsing the xsd file, the Annotation of the object System.Xml.Schema.XmlSchemaChoice is always null.
The code part:
public List<FSBaseItem> Parse( XmlTextReader xsdReader )
{
try
{
// prepare schema set for schema validation and raw template xsd "enrichment"
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.ValidationEventHandler += ValidationCallbackOne;
// include base schema
XmlSchema baseXsd = FlexXmlSchemaReader.ReadBase();
schemaSet.Add( baseXsd );
// The Read method will throw errors encountered on parsing the schema
XmlSchema xsd = XmlSchema.Read( xsdReader, ValidationCallbackOne );
schemaSet.Add( xsd );
// The Compile method will throw errors encountered on compiling the schema
schemaSet.Compile();
// create root
FSElement rootElement = new FSElement( this.GetNewId() );
// traverse body
this.TraverseSOM( xsd, rootElement );
// validate
this.ValidateFSItems( rootElement.Items );
// init lists containers with minimum elements
InitEmptyFEListItems( rootElement );
return rootElement.Items;
}
finally
{
xsdReader.Close();
}
}
Already in the beginning the choice element annotation is null. Could somebody give some working sample or add some hints?
Annotations certainly can be put inside xs:choice. Look at the following xsd taken from Inline Annotated Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:version="1.0" jaxb:extensionBindingPrefixes="xjc">
<xs:annotation>
<xs:appinfo>
<jaxb:globalBindings>
<xjc:superClass name="com.syh.Shape"/>
</jaxb:globalBindings>
</xs:appinfo>
</xs:annotation>
<xs:element name="Widgets">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="Shapes"/>
</xs:appinfo>
</xs:annotation>
<xs:element name="Rectangle" type="Rectangle"/>
<xs:element name="Square" type="Square"/>
<xs:element name="Circle" type="Circle"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="Rectangle">
<xs:sequence>
<xs:element name="Width" type="xs:integer"/>
<xs:element name="Height" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Square">
<xs:sequence>
<xs:element name="Length" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Circle">
<xs:sequence>
<xs:element name="Radius" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Adapting similar strategy to your xsd yields something like the following:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.es.de/es3/flex/simple"
elementFormDefault="qualified"
xmlns="http://www.es.de/es3/flex/simple"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:flex="http://www.es.de/es3/flex/flexBase">
<xs:import namespace="http://www.es.de/es3/flex/flexBase" />
<xs:element name="ESS3754">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:appinfo>
<flex:ControlHeadline>Headline_VVVVV</flex:ControlHeadline>
<flex:helpText>HelpText_VVVVV</flex:helpText>
</xs:appinfo>
</xs:annotation>
<xs:element name="String1" type="xs:string" minOccurs="1" maxOccurs="10"/>
<xs:element name="NewlyAdded" type="Coordinate" minOccurs="1" maxOccurs="10"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="Coordinate">
<xs:sequence>
<xs:element name="LocationX" type="xs:integer"/>
<xs:element name="LocationY" type="xs:integer"/>
<xs:element name="LocationZ" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
and the xsd is perfectly valid and looks like the following in Visual Studio [XSD] Desginer:
Update 1
I agree on the fact that debugger shows item annotation as null [I could not find it either but I should] and it is quite frustrating. I reconstructed the document using the code and you can annotate your element using the following workaround:
Consider the following XSD which does not have any XmlSchemaChoice and is saved as stack-problem2.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.es.de/es3/flex/simple"
elementFormDefault="qualified"
xmlns="http://www.es.de/es3/flex/simple"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:flex="http://www.es.de/es3/flex/flexBase">
<xs:import namespace="http://www.es.de/es3/flex/flexBase" />
<xs:complexType name="Coordinate">
<xs:sequence>
<xs:element name="LocationX" type="xs:integer"/>
<xs:element name="LocationY" type="xs:integer"/>
<xs:element name="LocationZ" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Now you can load this into memory and add annotations programmatically to the XmlSchemaChoice element:
public void Parse()
{
try
{
XmlTextReader reader2 = new XmlTextReader(#"stack-problem2.xsd");
XmlSchema myschema2 = XmlSchema.Read(reader2, ValidationCallback);
var simpleAnotation = new XmlSchemaAnnotation();
simpleAnotation.Id = "Lost Anotation";
// <xs:complexType name="ESS3754">
XmlSchemaComplexType complexType = new XmlSchemaComplexType();
myschema2.Items.Add(complexType);
complexType.Name = "ESS3754";
// <xs:choice minOccurs="1" maxOccurs="1">
XmlSchemaChoice choice = new XmlSchemaChoice();
complexType.Particle = choice;
choice.MinOccurs = 1;
choice.MaxOccurs = 1;
XmlSchemaElement elementSelected = new XmlSchemaElement();
choice.Items.Add(elementSelected);
elementSelected.Name = "String1";
AnnonateMyComplexType(choice);
FileStream file = new FileStream(#"satck-solution.xsd", FileMode.Create, FileAccess.ReadWrite);
XmlTextWriter xwriter = new XmlTextWriter(file, new UTF8Encoding());
xwriter.Formatting = Formatting.Indented;
myschema2.Write(xwriter);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public static void AnnonateMyComplexType(XmlSchemaChoice xmlSchemaComplexType)
{
XmlSchemaAnnotation myCustomAnnotation = new XmlSchemaAnnotation();
xmlSchemaComplexType.Annotation = myCustomAnnotation;
// <xs:documentation>State Name</xs:documentation>
XmlSchemaDocumentation schemaDocumentation = new XmlSchemaDocumentation();
myCustomAnnotation.Items.Add(schemaDocumentation);
schemaDocumentation.Markup = TextToNodeArray("Headline_VVVVV");
// <xs:appInfo>Application Information</xs:appInfo>
XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo();
myCustomAnnotation.Items.Add(appInfo);
appInfo.Markup = TextToNodeArray("Headline_VVVVV");
}
static void ValidationCallback(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.Write("WARNING: ");
else if (args.Severity == XmlSeverityType.Error)
Console.Write("ERROR: ");
Console.WriteLine(args.Message);
}
Running above will return the following XSD file:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="http://www.es.de/es3/flex/simple" xmlns:flex="http://www.es.de/es3/flex/flexBase" xmlns:mstns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" targetNamespace="http://www.es.de/es3/flex/simple" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://www.es.de/es3/flex/flexBase" />
<xs:complexType name="Coordinate">
<xs:sequence>
<xs:element name="LocationX" type="xs:integer" />
<xs:element name="LocationY" type="xs:integer" />
<xs:element name="LocationZ" type="xs:integer" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ESS3754">
<xs:choice minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>Headline_VVVVV</xs:documentation>
<xs:appinfo>Headline_VVVVV</xs:appinfo>
</xs:annotation>
<xs:element name="String1" />
</xs:choice>
</xs:complexType>
</xs:schema>
So to answer your first question: Yes, Annotation can be definitely put inside XmlSchemaChoice elements (Both through code and directly) [Not necessarily outside xmlSchemaChoice as the top element based on your experiment] and to address your second problem: [I had similar experience as of yours! It shows the annotation as null although it is not]
For anyone else running into this issue, I have found by reflecting the classes of the System.Xml.Schema namespace that, upon compiling a schemaset, the annotations of elements are copied to their children.
So Vytas999 should be able (as I have been able) to find his missing annotation by inspecting the XmlSchemaParticle objects in the XmlSchemaChoice.Items property.
I ran into the same problem - I needed to process an XSD provided by external entity and the Annotation of XmlSchemaChoice was always null.
Elaborating on #Adrian's answers the code I successfully use is below. In my case I traverse the schema from the root down, when I hit XmlSchemaSequence I itereate over its Items collection:
var index = 0;
foreach (var childObject in sequence.Items)
{
ExtractElement(childObject, index);
++index ;
}
When childObject is of type XmlSchemaChoice (assuming it is in variable xmlSchemaChoice, then instead of
// DOES NOT WORK - always null
var choiceAnnotation = xmlSchemaChoice.Annotation
I access the Annotation like this:
((xmlSchemaChoice.Parent as XmlSchemaSequence)?.Items[index] as XmlSchemaChoice)?.Annotation
Would you expect the same result? Well, it is not..
This code is just sample snippet describing accessing the Annotation via Parent's Items, it is NOT general purpose code and might need some adaptation to your exact case.