当引用的模式文件位于不同的项目/程序集中时,如何在VS中指定XSD schemaLocation属性?

时间:2009-07-01 23:43:08

标签: xml visual-studio xsd

编辑请参阅我的解决方案 / EDIT

我有一个包含两个项目的Visual Studio解决方案。

  • 项目1(称为ReferencedProject)包含XML模式文件(ReferencedSchema.xsd)。
  • Project 2(称之为MainProject)包含ReferencedProject作为参考。 MainProject还有一个模式文件(MainSchema.xsd)。

MainSchema.xsd包含以下代码:

<?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>

因为ReferencedSchema.xsd不在同一个文件夹中(它甚至不在同一个项目中),所以我收到错误消息“ReferencedSchema.xsd无法解析”。有道理。

如果我将xs:include元素编辑到此...

<xs:include schemaLocation="../../ReferencedProject/Data/ReferencedSchema.xsd" />

......错误消失了。但请注意,我提供了一个相对路径,该路径只能在我的解决方案的文件夹层次结构中。当我在编辑器中查看模式时,这很好,但在编译项目时却不是很好。如果我在编译后查看“bin”文件夹,则文件夹层次结构完全不同(两个xsd文件实际上最终位于同一文件夹中)。

我尝试使用Visual Studio的“将现有项目添加为链接”功能解决此问题,将ReferencedSchema.xsd文件的快捷方式放在与我的主模式文件相同的文件夹中,但这不起作用。 XSD验证器显然无法假装链接是实际文件。

所以,我的问题是似乎没有任何我可以为schemaLocation提供的uri在两种情况下都是有效的(在解决方案资源管理器中和运行时)。有没有人有任何建议?

谢谢!

修改

我决定这样做:

<xs:include schemaLocation="../../ReferencedProject/Data/ReferencedSchema.xsd" />

只要我在Visual Studio中查看内容,这是正确的,在运行我的代码时不正确。

为了使它在运行时也能工作,我使用正确的相对引用动态替换schemaLocation,如下所示:

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;
    }

我选择了这个解决方案,因为无论我在Visual Studio中查看XML和XSD文件,还是在运行/调试我的应用程序,现在一切都能正常工作。

3 个答案:

答案 0 :(得分:9)

XSD仅支持URI位置,而不支持路径位置。这意味着file:///C:/path/to/VS/Projects/ReferencedProject/Data/ReferencedSchema.xsd有效,但不是../../ReferencedProject/Data/ReferencedSchema.xsd

答案 1 :(得分:1)

免责声明:我对XML架构了解不多。无论如何,我遇到了和你一样的问题。

使用xs:import而不是xs:include似乎解决了我在VS设计器中的问题。

第一个架构:

<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>

第二个架构:

<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>

在Visual Studio中编辑XML架构时,您可以使用菜单项XML - &gt;查看哪些架构处于活动状态。模式。

答案 2 :(得分:0)

使用公共URL或公共网络共享将两个文件放在该位置。