我正在使用一个Web服务来提供带有内联架构的XML数据。它看起来像Microsoft ADO的XML输出。模式包含完整的属性名称,而数据本身仅包含别名。
示例XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly">
<s:AttributeType name="c4" rs:name="FULLNAME" rs:number="5" />
<s:AttributeType name="c5" rs:name="FIRSTNAME" rs:number="6" />
<s:AttributeType name="c6" rs:name="MIDDLENAME" rs:number="7" />
<s:AttributeType name="c7" rs:name="LASTNAME" rs:number="8" />
<s:AttributeType name="c8" rs:name="ADDRESSLINE1" rs:number="9" />
<s:AttributeType name="c9" rs:name="ADDRESSLINE2" rs:number="10" />
<s:AttributeType name="c10" rs:name="CITY" rs:number="11" />
<s:AttributeType name="c11" rs:name="POSTALCODE" rs:number="12" />
<s:AttributeType name="c12" rs:name="STATE" rs:number="13" />
</s:ElementType>
</s:Schema>
<rs:data>
<z:row c4="Jane Frickin Doe"
c5="Jane"
c6="Frickin"
c7="Doe"
c8="1234 Fifth Ave"
c9=""
c10="Anywhere"
c11="98765"
c12="US"/>
</rs:data>
</xml>
我可以将它拉到XDocument中,然后使用:
遍历记录For Each person In personRecs...<z:row>
Dim firstName as String = person.@c5
Next
然而,这会出现问题,因为字段顺序可以随着字段的添加或删除而任意改变(如果在其之前添加了另一个字段,则第一个名称可能是@ c6。)那么如何使用person.@FIRSTNAME
呢?
答案 0 :(得分:2)
冒着说明显而易见的风险 - 以及对我来说过去的爆炸:) - 因为它是一个真正的ADO记录集xml,你可以将它推入ADO记录集,你肯定会有命名的字段访问权限
您需要在项目中引用.net“ADODB”。 然后你可以拥有以下内容:
string strInputXML;
strInputXML = string.Concat(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<xml xmlns:s=\"uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882\" ",
"xmlns:dt=\"uuid:C2F41010-65B3-11d1-A29F-00AA00C14882\" ",
"xmlns:rs=\"urn:schemas-microsoft-com:rowset\" ",
"xmlns:z=\"#RowsetSchema\">",
"<s:Schema id=\"RowsetSchema\">",
" <s:ElementType name=\"row\" content=\"eltOnly\">",
" <s:AttributeType name=\"c4\" rs:name=\"FULLNAME\" rs:number=\"5\" />",
" <s:AttributeType name=\"c5\" rs:name=\"FIRSTNAME\" rs:number=\"6\" />",
" <s:AttributeType name=\"c6\" rs:name=\"MIDDLENAME\" rs:number=\"7\" />",
" <s:AttributeType name=\"c7\" rs:name=\"LASTNAME\" rs:number=\"8\" />",
" <s:AttributeType name=\"c8\" rs:name=\"ADDRESSLINE1\" rs:number=\"9\" />",
" <s:AttributeType name=\"c9\" rs:name=\"ADDRESSLINE2\" rs:number=\"10\" />",
" <s:AttributeType name=\"c10\" rs:name=\"CITY\" rs:number=\"11\" />",
" <s:AttributeType name=\"c11\" rs:name=\"POSTALCODE\" rs:number=\"12\" />",
" <s:AttributeType name=\"c12\" rs:name=\"STATE\" rs:number=\"13\" />",
" </s:ElementType>",
"</s:Schema>",
"<rs:data>",
"<z:row c4=\"Jane Frickin Doe\"",
" c5=\"Jane\"",
" c6=\"Frickin\"",
" c7=\"Doe\"",
" c8=\"1234 Fifth Ave\"",
" c9=\"\"",
" c10=\"Anywhere\"",
" c11=\"98765\"",
" c12=\"US\"/>",
"</rs:data>",
"</xml>"
);
//--- interestingly, you have to drop the xml declaration
// I'll be lazy and cut it as a string for this example
strInputXML = strInputXML.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "");
//--- And we can load an actual ADODB.recordset with it, for named field access
ADODB.Stream objADOStream = new ADODB.Stream();
objADOStream.Open();
objADOStream.WriteText(strInputXML);
objADOStream.Position = 0;
ADODB.Recordset objRS = new ADODB.Recordset();
objRS.Open(objADOStream);
Console.WriteLine (objRS.Fields["FULLNAME"].Value);
答案 1 :(得分:0)
您可以通过编程方式访问架构吗?也就是说,像读取XML文档的任何其他部分一样阅读它?
我在模式中读取并构建Dictionary<string, string>
以将字段名称(FIRSTNAME等)映射到标记(C4-C12),并按字段名称查找标记名称。
我的VB生锈了,但如果你愿意,我可以用C#给你一些示例代码。
答案 2 :(得分:0)
您可以像这样获取FIRSTNAME的属性名称:
Dim firstNameAttributeName As String = (
From attr
In doc...<s:AttributeType>
Where attr.@rs:name = "FIRSTNAME"
Select attr.@name
).First()
(其中doc
是您的XDocument
对象)然后,您可以在任何给定元素上获取该属性的值,如下所示:
Dim personName As String = person.Attribute(firstNameAttributeName).Value
(其中person
是XElement
个对象)这样做,显然需要以下Imports
:
Imports <xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882">
Imports <xmlns:rs="urn:schemas-microsoft-com:rowset">
Imports <xmlns:z="#RowsetSchema">