2012-04-17 167 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