2012-04-17 32 views
1

解析XML我寫的XSD爲XML配置文件,像這樣:與定製模式/命名空間

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:t="http://www.foo.com/schemas/datatransfer" 
      targetNamespace="http://www.foo.com/schemas/datatransfer" 
      attributeFormDefault="unqualified" elementFormDefault="qualified"> 
    <xs:element name="transferGroups"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="transferGroup" maxOccurs="unbounded"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="connectionString" type="xs:string" /> 
       <xs:choice minOccurs="1" maxOccurs="1"> 
       <xs:element name="script" minOccurs="0" maxOccurs="1"> 
        <xs:complexType> 
        <xs:attribute name="path" type="xs:string" use="required" /> 
        <xs:attribute name="fileName" type="xs:string" use="required" /> 
        <xs:attribute name="useCompression" type="xs:boolean" use="required" /> 
        </xs:complexType> 
       </xs:element> 
       <xs:element name="table" minOccurs="0" maxOccurs="1"> 
        <xs:complexType> 
        <xs:attribute name="name" type="xs:string" use="required" /> 
        <xs:attribute name="fileName" type="xs:string" use="required" /> 
        <xs:attribute name="useCompression" type="xs:boolean" use="required" /> 
        </xs:complexType> 
       </xs:element> 
       <xs:element name="tables" minOccurs="0" maxOccurs="1"> 
        <xs:complexType> 
        <xs:sequence> 
         <xs:element name="table" maxOccurs="unbounded" minOccurs="1"> 
         <xs:complexType> 
          <xs:attribute name="name" type="xs:string" use="required" /> 
          <xs:attribute name="fileName" type="xs:string" use="required" /> 
          <xs:attribute name="useCompression" type="xs:boolean" use="required" /> 
         </xs:complexType> 
         </xs:element> 
        </xs:sequence> 
        </xs:complexType> 
       </xs:element> 
       </xs:choice> 
       <xs:element name="format"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element name="addHeaderRow"> 
         <xs:complexType> 
         <xs:attribute name="value" type="xs:boolean" use="required" /> 
         </xs:complexType> 
        </xs:element> 
        <xs:element name="columnsDelimitedBy"> 
         <xs:complexType> 
         <xs:attribute name="value" type="xs:string" use="required" /> 
         </xs:complexType> 
        </xs:element> 
        <xs:element name="rowsDelimitedBy"> 
         <xs:complexType> 
         <xs:attribute name="value" type="xs:string" use="required" /> 
         </xs:complexType> 
        </xs:element> 
        </xs:sequence> 
       </xs:complexType> 
       </xs:element> 
       <xs:element name="transferSite"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element name="protocol"> 
         <xs:complexType> 
         <xs:attribute name="value" type="xs:string" use="required" /> 
         <xs:attribute name="address" type="xs:string" use="required" /> 
         <xs:attribute name="port" type="xs:unsignedByte" use="required" /> 
         </xs:complexType> 
        </xs:element> 
        <xs:element name="credentials"> 
         <xs:complexType> 
         <xs:attribute name="userName" type="xs:string" use="required" /> 
         <xs:attribute name="password" type="xs:string" use="required" /> 
         </xs:complexType> 
        </xs:element> 
        <xs:element name="destinationFolder"> 
         <xs:complexType> 
         <xs:attribute name="value" type="xs:string" use="required" /> 
         </xs:complexType> 
        </xs:element> 
        </xs:sequence> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      <xs:attribute name="useCompression" type="xs:boolean" use="required" /> 
      <xs:attribute name="fileName" type="xs:string" use="optional" /> 
      </xs:complexType> 
     </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

我產生(然後修改)的模式從我在Visual Studio設計像這樣的XML文件:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 
<transferGroups> 
    <transferGroup useCompression="false" > 
    <connectionString>DSN=MyDSN;uid=foo;password=bar;</connectionString> 
    <tables> 
     <table name="dbo.Foo1" fileName="E:\Files\Foo1_{0:yyyyMMdd}.gz" useCompression="true" /> 
     <table name="pub.Foo2" fileName="E:\Files\Foo2_{0:yyyyMMdd}.gz" useCompression="true" /> 
    </tables> 
    <format> 
     <addHeaderRow value="true"/> 
     <columnsDelimitedBy value="|" /> 
     <rowsDelimitedBy value="\r\n" /> 
    </format> 
    <transferSite> 
     <protocol value="FTP" address="localhost" port="21" /> 
     <credentials userName="anonymous" password="[email protected]" /> 
     <destinationFolder value="/" /> 
    </transferSite> 
    </transferGroup> 
</transferGroups> 

在實踐中,我做了一個配置文件,像這樣:

<transferGroups xmlns="http://www.foo.com/schemas/datatransfer"> 
    <transferGroup useCompression="false" > 
    <connectionString>some connection string</connectionString> 
    <tables> 
     <table name="tableName1" fileName="tableName1_{0:yyyyMMdd}.gz" useCompression="true" /> 
     <table name="tableName2" fileName="tableName2_{0:yyyyMMdd}.gz" useCompression="true" /> 
    </tables> 
    <format> 
     <addHeaderRow value="true"/> 
     <columnsDelimitedBy value="|" /> 
     <rowsDelimitedBy value="\r\n" /> 
    </format> 
    <transferSite> 
     <protocol value="FTP" address="ftp.someplace.com" port="21" /> 
     <credentials userName="foo" password="bar" /> 
     <destinationFolder value="subFolder1" /> 
    </transferSite> 
    </transferGroup> 
</transferGroups> 

我不知道,但是,規範ifying命名空間/模式改變了解析XmlDocument中的文件的方式。例如,這個代碼段將捕獲一個XmlNodeXmlNodeList如果我沒有指定的模式,但一旦指定的架構,沒有節點匹配:

var xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(myXml); 
var transferGroupNodes = xmlDoc.SelectNodes("//transferGroups/transferGroup") 
    .OfType<XmlNode>(); 

我怎麼會收集分析的transferGroup節點在這個情況下?我無法在網上找到一個體面的例子來向我展示如何做到這一點。

+0

你*是否使用XmlDocument? LINQ to XML使得所有這一切變得非常簡單......假設你使用.NET 3.5(如果你使用的是LINQ ...) – 2012-04-17 18:18:36

+0

那麼...... *必須*是一個很強的術語。我寧願;我確信有一種方法可以做到這一點,我想知道它將如何完成。我在我的代碼中的其他地方使用'XmlNode's和'XmlDocument's。 – 2012-04-17 18:22:17

+0

如果您將* all *更改爲LINQ to XML,則其餘代碼可能會變得更清晰。你可以在XPath中使用'XmlNamespaceManager',但是與LINQ to XML的清潔相比,這是非常糟糕的。我強烈建議在轉換儘快開始:) – 2012-04-17 18:23:39

回答

1

模式與您的問題無關 - 您的節點具有名稱空間,因此需要相應地更改XPath。正如Jon Skeet指出LINQ to XML將使它更易於使用,但仍然需要選擇具有正確名稱空間的節點。

在XPath中使用名稱空間的問題已多次討論 - 從FAQ答案開始 - Using Xpath With Default Namespace in C#

使用XPath忽略名稱空間的作弊方式:"//*[ local-name() = 'justName']"

+0

謝謝!解決了我的問題。我將不得不考慮LINQ to XML ...這個XmlDocument的東西是爲鳥類。 – 2012-04-17 19:08:26