VB.NET从内联架构解析XML别名

时间:2014-01-08 20:47:24

标签: xml vb.net

我正在使用一个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呢?

3 个答案:

答案 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

(其中personXElement个对象)这样做,显然需要以下Imports

Imports <xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882">
Imports <xmlns:rs="urn:schemas-microsoft-com:rowset">
Imports <xmlns:z="#RowsetSchema">