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

3

从Ruby世界回来后,我期望在C#中也能看到类似的XML-to-hash映射工具。

以下是源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
为什么不直接定义适当的C#类,然后使用XmlSerializer进行反序列化呢? - dbc
1个回答

3
这是一种实现方式。
  1. You'll need to add the relevant references first (here's a few):

    using System.Linq;

    using System.Xml.Linq;

    using System.Text;

    using System.Xml;

    using System.Xml.Serialization;

  2. Create a wrapper class that will hold the deserialized data.

    [XmlRoot("root")]
    public class root
    {
        [XmlElement("MyObject")]
        public List<MyObject> A_Object
        {
            get;
            set;
        }
    }
    
  3. Then the class that will hold the deserialized data, for example here it's MyObject:

    public class 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;
    }
    

    }

*注意:如果您想要跟踪但不反序列化的属性,则可以使用没有[XmlElement]的属性。

  1. 最后,将XML反序列化为对象列表:

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. 然后,您可以按照自己的需要对其进行操作,例如,以其他方式重新序列化它。


相关教程:https://dev59.com/OXRC5IYBdhLWcg3wP-hh 同时别忘了在MyObject和root类中添加serializable。 :) - matrixanomaly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接