将XML节点轻松映射到对象的属性

时间:2015-03-31 18:21:39

标签: c# xml xpath mapping

从Ruby世界返回其XML-to-hash映射的容易性,我期待在C#中看到类似的内容。

以下是源XML:

<whois-resources xmlns:xlink="http://www.w3.org/1999/xlink">
    <service name="search"/>
    <parameters>
        <inverse-lookup/>
        <type-filters/>
        <flags/>
        <query-strings>
            <query-string value="....."/>
        </query-strings>
        <sources/>
    </parameters>
    <objects>
        <object type="inetnum">
            <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/inetnum/....."/>
            <source id="ripe"/>
            <primary-key>
                <attribute name="inetnum" value="....."/>
            </primary-key>
            <attributes>
                <attribute name="inetnum" value="....."/>
                <attribute name="netname" value="....."/>
                <attribute name="descr" value="....."/>
                <attribute name="descr" value="....."/>
                <attribute name="country" value="....."/>
                <attribute name="admin-c" value="....." referenced-type="person">
                    <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/person/....."/>
                </attribute>
                <attribute name="tech-c" value="....." referenced-type="person">
                    <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/person/....."/>
                </attribute>
                <attribute name="status" value="ASSIGNED PA"/>
                <attribute name="mnt-by" value="....." referenced-type="mntner">
                    <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/mntner/....."/>
                </attribute>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="source" value="....." comment="Filtered"/>
            </attributes>
            <tags>
                <tag id="RIPE-USER-RESOURCE"/>
            </tags>
        </object>
        <object type="person">
            <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/person/....."/>
            <source id="ripe"/>
            <primary-key>
                <attribute name="nic-hdl" value="....."/>
            </primary-key>
            <attributes>
                <attribute name="person" value="....."/>
                <attribute name="address" value="....."/>
                <attribute name="address" value="....."/>
                <attribute name="address" value="....."/>
                <attribute name="phone" value="....."/>
                <attribute name="fax-no" value="....."/>
                <attribute name="nic-hdl" value="....."/>
                <attribute name="mnt-by" value="....." referenced-type="mntner">
                    <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/mntner/....."/>
                </attribute>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="source" value="....." comment="Filtered"/>
            </attributes>
        </object>
        <object type="route">
            <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/route/....."/>
            <source id="ripe"/>
            <primary-key>
                <attribute name="route" value="....."/>
                <attribute name="origin" value="....."/>
            </primary-key>
            <attributes>
                <attribute name="route" value="....."/>
                <attribute name="descr" value="....."/>
                <attribute name="origin" value="....." referenced-type="aut-num">
                    <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/aut-num/....."/>
                </attribute>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="remarks" value="....."/>
                <attribute name="mnt-by" value="....." referenced-type="mntner">
                    <link xlink:type="locator" xlink:href="http://rest.db.ripe.net/ripe/mntner/....."/>
                </attribute>
                <attribute name="source" value="....." comment="Filtered"/>
            </attributes>
        </object>
    </objects>
    <terms-and-conditions xlink:type="locator" xlink:href="http://www.ripe.net/db/support/db-terms-conditions.pdf"/>
</whois-resources>

我想重新映射到具有以下结构的对象:

{
    Service: {
        Name: "....."
    },
    Parameters: {
        QueryStrings: [".....", "....."]
    },
    Inetnum: {
        Link: {
            Type: ".....",
            Href: "....."
        },
        Source: {
            id: "....."
        },
        PrimaryKey: {
            Inetnum: "....."
        },
        Attr: {
            Inetnum: ".....",
            Netname: ".....",
            Descr: ".....",
            Country: ".....",
            AdminC: {
                Value: ".....",
                ReferencedType: ".....",
                Link: {
                    Type: ".....",
                    Href: "....."
                }
            },
            TechC: {
                Value: ".....",
                ReferencedType: ".....",
                Link: {
                    Type: ".....",
                    Href: "....."
                }
            },
            Status: ".....",
            MntBy: {
                Value: ".....",
                ReferencedType: ".....",
                Link: {
                    Type: ".....",
                    Href: "....."
                }
            }
            Remarks: ".....", #a concatenation of all remarks nodes
            Source: {
                Value: ".....",
                Comment: "....."
            }
        },
        Tags: [
            { id: "....." }
        ]
    },
    Person {
        Link: {
            Type: ".....",
            Href: "....."
        },
        Source: {
            id: "....."
        }
        PrimaryKey: {
            NicHdl: "....."
        },
        Attr: {
            Person: ".....",
            Address: ".....", #a concatenation of all address nodes
            Phone: ".....",
            FaxNo: ".....",
            NicHdl: ".....",
            MntBy: {
                Value: ".....",
                ReferencedType: ".....",
                Link: {
                    Type: ".....",
                    Href: "....."
                }
            }
            Remarks: ".....", #a concatenation of all remarks nodes
            Source: {
                Value: ".....",
                Comment: "....."
            }
        }
    },  
    Route: {
        Link: {
            Type: ".....",
            Href: "....."
        },
        Source: {
            id: "....."
        },
        PrimaryKey: {
            Route: ".....",
            Origin: "....."
        },
        Attr: {
            Route: ".....",
            Descr: ".....",
            Origin: {
                Value: ".....",
                ReferencedType: ".....",
                Link: {
                    Type: ".....",
                    Href: "....."
                }
            },
            Remarks: ".....", #a concatenation of all remarks nodes
            MntBy: {
                Value: ".....",
                ReferencedType: ".....",
                Link: {
                    Type: ".....",
                    Href: "....."
                }
            },
            Source: {
                Value: ".....",
                Comment: "....."
            }
        }
    },
    TermsAndConditions: {
        Type: ".....",
        Href: "....."
    }
}

能够调用以下属性:

whois.Inetnum.Attr.Netname

我完全不喜欢通过调用SelectSingleNode("xpath");

来检索每个节点

期望的过程是:

  1. 定义接收器对象及其所有子对象
  2. 定义映射规则
  3. 使用单个方法调用解析XML字符串

1 个答案:

答案 0 :(得分:2)

这是一种做法。

  1. 您需要先添加相关参考资料(这里有几个):

    using System.Linq;

    using System.Xml.Linq;

    using System.Text;

    using System.Xml;

    using System.Xml.Serialization;

  2. 创建一个包含反序列化数据的包装类。

    [XmlRoot("root")]
    public class root
    {
        [XmlElement("MyObject")]
        public List<MyObject> A_Object
        {
            get;
            set;
        }
    }
    
  3. 然后是保存反序列化数据的类,例如这里是MyObject:

    公共类MyObject {

    [XmlElement("type")] //from your sample code route,person all go here
    public string objType
    {
        get;
        set;
    }
    [XmlElement("address")]
    public string personAddr
    {
        get;
        set;
    }
    [XmlElement("phone")]
    public string personPhone
    {
        get;
        set;
    }
    

    }

  4. *注意:如果您有想要跟踪的属性,但没有反序列化,那么您可以拥有那些没有[XmlElement]的特性。

    1. 最后将XML反序列化为对象列表:
    2. public List<myObject> DeserializeXML(string xmlPath) { XmlSerializer deserializer = new XmlSerializer(typeof(root)); List<myObject> objectList = new List<myObject>(); try { using (TextReader textReader = new StreamReader(xmlPath)) { root setOfObjects; setOfObjects = (root)deserializer.Deserialize(textReader); } objectList = setOfObjects.A_Object; } catch(FileNotFoundException a) { } return objectList; } 5.然后你可以继续操作它以你喜欢的任何形式,也许再次以不同的方式序列化。