Dot-Net

使用 .NET 針對架構驗證 XML

  • December 11, 2012

我想測試(真或假)任意 XML 文件是否與給定模式匹配。

值得一提的是,該架構是 Word 2003 WordML 架構,Microsoft 使用大約 7 個*.xsd文件的列表來定義它。

這些文件之一還包括 W3Cxml.xsd文件,包括以下語句:

<xsd:import id="xml" namespace="http://www.w3.org/XML/1998/namespace"
   schemaLocation="http://www.w3.org/2001/xml.xsd"></xsd:import>

我正在使用如下所示的 .NET 程式碼進行驗證:

  public static void validate(string filename)
   {
      XmlReaderSettings settings = new XmlReaderSettings();
      settings.Schemas.Add(
          "http://schemas.microsoft.com/office/word/2003/wordml",
          //to get this file I downloaded "Office 2003: XML Reference Schemas", i.e. "Office2003XMLSchema.exe" 
          @"C:\Program Files\Microsoft Office 2003 Developer Resources\Microsoft Office 2003 XML Reference Schemas\WordprocessingML Schemas\wordnet.xsd"
          );
       settings.ValidationType = ValidationType.Schema;
       settings.ValidationEventHandler += new ValidationEventHandler(validationEventHandler);
       XmlReader xmlReader = XmlReader.Create(filename, settings);
       while (xmlReader.Read()) { }
  }

我的問題是,如果我在未連接到網際網路的機器上執行此程式碼,那麼我會收到一個XmlSchemaValidationException錯誤,大意是它 can’t find xml.xsd

為了解決這個問題,我下載了 xml.xsd 的副本,並使用以下settings.Schemas.Add方法顯式添加它:當機器未連接到 Internet 時,驗證現在可以正常工作。

但是,當機器連接到網際網路時,我現在收到一條錯誤消息The global attribute 'http://www.w3.org/XML/1998/namespace:lang' has already been declared.

所以顯然我需要明確添加它,或者我不需要,這取決於機器是否能夠從網際網路上靜默下載它(或者甚至可能以前能夠下載它,並將它記憶體在某個地方)。

所以,它是“如果我這樣做該死,如果我不這樣做該死”。我是否需要以一種方式嘗試,擷取異常,然後以另一種方式嘗試?還是有更優雅的解決方案?

我們看不到您的程式碼,但在許多實現中,這是通過使用目錄解析器將 .xsd 的請求重定向到本地副本來處理的。有一個可用於此的屬性XmlReaderSettings.XmlResolver 。請參閱XMLCatalog.net,了解您可以使用的 Apache 許可實現。

這樣做的一個副作用是您可以將所有模式記憶體在本地。這一點尤其重要,因為 W3C 會阻止對其站點的過度讀取,並且您的程式碼(或更糟糕的是,您的客戶的程式碼)會隨機開始失敗。

引用自:https://stackoverflow.com/questions/3449180