Простая привязка узлов XML к свойствам объекта

1

Возвращаясь из мира Ruby с легкостью сопоставления 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 ?
Теги:
xpath
mapping

1 ответ

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:

    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; } 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. Затем вы можете продолжить и манипулировать им в любой форме, какой вам нравится, может быть, снова сериализуйте ее по-другому.

  • 0
    Связанное руководство: stackoverflow.com/questions/364253/… также не забудьте добавить сериализуемый в MyObject и корневых классах. :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню