【发布时间】:2012-04-17 18:13:03
【问题描述】:
我为这样的 XML 配置文件编写了 XSD:
<?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="test@myserver.com" />
<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>
然而,我没有意识到指定命名空间/模式会改变解析XmlDocument 中文件的方式。例如,如果我没有指定架构,这段代码将捕获一个XmlNodeList 和一个XmlNode,但是一旦指定了架构,就没有节点匹配:
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(myXml);
var transferGroupNodes = xmlDoc.SelectNodes("//transferGroups/transferGroup")
.OfType<XmlNode>();
在这种情况下,我将如何收集 transferGroup 节点进行解析?我在网上找不到一个像样的例子来告诉我如何做到这一点。
【问题讨论】:
-
你有使用XmlDocument吗? LINQ to XML 让这一切变得非常简单...如果您使用的是 LINQ,那么您可能正在使用 .NET 3.5...
-
嗯... 必须 是一个强有力的术语。我更愿意;我确信有办法做到这一点,我想知道如何做到这一点。在我的代码中的其他任何地方,我都在使用
XmlNodes 和XmlDocuments。 -
如果您将其 all 更改为 LINQ to XML,其余代码可能会变得更加简洁。您可以将
XmlNamespaceManager与XPath 一起使用,但与LINQ to XML 的简洁性相比,这太可怕了。我强烈建议尽快开始过渡:) -
Using Xpath With Default Namespace in C# 的可能副本。请注意,模式与您的问题无关 - 您有带有名称空间的节点,因此需要相应地更改 XPath。正如 Jon Skeet 指出的那样,LINQ to XML 将使其更易于使用,但您仍然需要选择具有正确命名空间的节点。
-
这似乎是简短的回答,@AlexeiLevenkov。乔恩,我将不得不研究 Linq To XML。
标签: c# xml xsd xml-parsing