EDIT See my solution below /EDIT
I have a Visual Studio solution with two projects.
MainSchema.xsd contains the following code:
<?xml version="1.0"?>
<xs:schema
xmlns="main"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="main"
targetNamespace="main"
elementFormDefault="qualified">
<xs:include schemaLocation="ReferencedSchema.xsd" />
...
</xs:schema>
Because ReferencedSchema.xsd is not in the same folder (it's not even in the same project), I get an error saying "ReferencedSchema.xsd could not be resolved." Makes sense.
If I edit the xs:include element to this...
<xs:include schemaLocation="../../ReferencedProject/Data/ReferencedSchema.xsd" />
...the error goes away. However, notice that I've provided a relative path to the schema that will only work within my solution's folder hierarchy. That's great when I'm viewing the schema in the editor but not so great when I compile my project. If I look in my "bin" folder after compiling, the folder hierarchy is completely different (the two xsd files actually end up in the same folder).
I tried to get around this using Visual Studio's "Add Existing Item As Link" feature, putting a shortcut to the ReferencedSchema.xsd file in the same folder as my main schema file, but that didn't work. The XSD validator apparently isn't capable of pretending the link is the actual file.
So, my problem is that there doesn't seem to be any uri I can provide for schemaLocation that will be valid in both situations (within the solution explorer and during runtime). Does anyone have any suggestions?
Thanks!
EDIT
I decided to go with this:
<xs:include schemaLocation="../../ReferencedProject/Data/ReferencedSchema.xsd" />
This is correct as long as I'm viewing things within Visual Studio, incorrect when running my code.
To make it work at runtime as well, I dynamically replace the schemaLocation with the correct relative reference as follows:
public class UriReplacingXmlValidator
{
public virtual XDocument Validate(
string dataFolderName,
string baseDataFolderName,
string xmlFileName,
string schemaFileName,
string baseSchemaFileName)
{
string rootFolderPath = Environment.CurrentDirectory + Path.DirectorySeparatorChar;
string dataFolderPath = rootFolderPath + Path.DirectorySeparatorChar + dataFolderName;
string baseDataFolderPath = rootFolderPath + Path.DirectorySeparatorChar + baseDataFolderName;
string xmlPath = dataFolderPath + Path.DirectorySeparatorChar + xmlFileName;
string schemaPath = dataFolderName + Path.DirectorySeparatorChar + schemaFileName;
string baseSchemaPath = baseDataFolderName + Path.DirectorySeparatorChar + baseSchemaFileName;
XDocument xmlDocument = XDocument.Load(xmlPath);
XDocument schemaDocument = XDocument.Load(schemaPath);
ResetBaseSchemaLocation(schemaDocument, baseSchemaPath);
XmlValidator validator = new XmlValidator();
bool isValid = validator.Validate(xmlDocument, schemaDocument);
if (isValid)
return xmlDocument;
else
return null;
}
protected virtual void ResetBaseSchemaLocation(XDocument schemaDocument, string baseSchemaPath)
{
XNamespace ns = "http://www.w3.org/2001/XMLSchema";
XAttribute attribute = schemaDocument.Element(ns + "schema").Element(ns + "redefine").Attribute("schemaLocation");
attribute.Value = baseSchemaPath;
}
I went with this solution because everything now works whether I'm viewing my XML and XSD files in Visual Studio or running/debugging my app.
The xsi:schemaLocation attribute locates schemas for elements and attributes that are in a specified namespace. Its value is a namespace URI followed by a relative or absolute URL where the schema for that namespace can be found. It is most commonly attached to the root element but can appear further down the tree.
Defining XML ElementsEach element definition within the XSD must have a 'name' property, which is the tag name that will appear in the XML document. The 'type' property provides the description of what type of data can be contained within the element when it appears in the XML document.
The 'noNamespaceSchemaLocation' attribute is used to reference XML Schema(s) that are not defined in a target-namespace.
XSD only supports URI locations, not path location. This means that file:///C:/path/to/VS/Projects/ReferencedProject/Data/ReferencedSchema.xsd
is valid, but not ../../ReferencedProject/Data/ReferencedSchema.xsd
.
Disclaimer: I don't know a lot about XML schema. Anyway, I ran into the same problem as you.
Using xs:import rather than xs:include seemed to solve my problem in VS designer.
First schema:
<xs:schema id="schema1"
targetNamespace="http://tempuri.org/schema1.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/schema1.xsd"
xmlns:mstns="http://tempuri.org/schema1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="MyType" nillable="true"/>
<xs:complexType name="MyType">
<xs:all>
<xs:element name="Value1" type="xs:double"/>
<xs:element name="Value2" type="xs:double"/>
</xs:all>
</xs:complexType>
</xs:schema>
Second schema:
<xs:schema id="schema2"
targetNamespace="http://tempuri.org/schema2.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/schema2.xsd"
xmlns:mstns="http://tempuri.org/schema2.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:schema1="http://tempuri.org/schema1.xsd"
>
<xs:import namespace="http://tempuri.org/schema1.xsd"/>
<xs:element name="MySecondType" nillable="true"/>
<xs:complexType name=MySecondType>
<xs:element name="Value" type="schema1:MyType/>
</xs:complexType>
</xs:schema>
When editing XML schema in Visual Studio, you can see which schema's are active using menu item XML --> Schemas.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With