具有重复元素名称的C#LINQ to XML查询具有属性

时间:2010-03-09 04:34:16

标签: c# .net xml linq linq-to-xml

        <Party id="Party_1">
            <PartyTypeCode tc="1">Person</PartyTypeCode>
            <FullName>John Doe</FullName>
            <GovtID>123456789</GovtID>
            <GovtIDTC tc="1">Social Security Number US</GovtIDTC>
            <ResidenceState tc="35">New Jersey</ResidenceState>
            <Person>
                <FirstName>Frank</FirstName>
                <MiddleName>Roberts</MiddleName>
                <LastName>Madison</LastName>                    
                <Prefix>Dr.</Prefix>
                <Suffix>III</Suffix>
                <Gender tc="1">Male</Gender>
                <BirthDate>1974-01-01</BirthDate>
                <Age>35</Age>
                <Citizenship tc="1">United States of America</Citizenship>
            </Person>
            <Address>
                <AddressTypeCode tc="26">Bill Mailing</AddressTypeCode>
                <Line1>2400 Meadow Lane</Line1>
                <Line2></Line2>
                <Line3></Line3>
                <Line4></Line4>
                <City>Somerset</City>
                <AddressStateTC tc="35">New Jersey</AddressStateTC>
                <Zip>07457</Zip>
                <AddressCountryTC tc="1">United States of America</AddressCountryTC>
            </Address>
        </Party>
        <!-- ***********************  -->
        <!--  Insured Information     -->
        <!-- ***********************  -->
        <Party id="Party_2">
            <PartyTypeCode tc="1">Person</PartyTypeCode>
            <FullName>Dollie Robert Madison</FullName>
            <GovtID>123956239</GovtID>
            <GovtIDTC tc="1">Social Security Number US</GovtIDTC>
            <Person>
                <FirstName>Dollie</FirstName>
                <MiddleName>R</MiddleName>
                <LastName>Madison</LastName>
                <Suffix>III</Suffix>
                <Gender tc="2">Female</Gender>
                <BirthDate>1996-10-12</BirthDate>
                <Citizenship tc="1">United States of America</Citizenship>
            </Person>
            <!-- Insured Address -->
            <Address>
                <AddressTypeCode tc="26">Bill Mailing</AddressTypeCode>
                <Line1>2400 Meadow Lane</Line1>
                <City>Somerset</City>
                <AddressStateTC tc="35">New Jersey</AddressStateTC>
                <Zip>07457</Zip>
                <AddressCountryTC tc="1">United States of America</AddressCountryTC>
            </Address>
            <Risk>
                <!-- Disability Begin Effective Date -->
                <DisabilityEffectiveStartDate>2006-01-01</DisabilityEffectiveStartDate>
                <!-- Disability End Effective Date -->
                <DisabilityEffectiveStopDate>2008-01-01</DisabilityEffectiveStopDate>
            </Risk>
        </Party>
        <!-- *******************************  -->
        <!--  Company Information     -->
        <!-- ******************************  -->
        <Party id="Party_3">
            <PartyTypeCode tc="2">Organization</PartyTypeCode>
            <Organization>
                <DTCCMemberCode>1234</DTCCMemberCode>
            </Organization>
            <Carrier>
                <CarrierCode>105</CarrierCode>
            </Carrier>
        </Party>

这是我的代码无效,因为第3方不包含FullName,我知道如果我只返回name属性,partyelements包含3方。有没有办法循环遍历每个标签?

        var partyElements = from party in xmlDoc.Descendants("Party")
           select new
           {
               Name = party.Attribute("id").Value,
               PartyTypeCode = party.Element("PartyTypeCode").Value,
               FullName = party.Element("FullName").Value,
               GovtID = party.Element("GovtID").Value,
           };

3 个答案:

答案 0 :(得分:1)

这些方面的内容怎么样? (更多的想法/建议而不是实现,因为我不知道你的对象模型)

var parties = xmlDoc.Descendants("Party");
foreach(var party in parties)
{
    int partyTypeCode = party.Element("PartyTypeCode").Value;
    if(partyTypeCode == 1)
    {
        var person = personFactory.Build(party);
        // do something
    }
    else if(partyTypeCode == 2)
    {
        var organization = companyFactory.Build(party);
        // do something
    }
}

在一个完美的多态世界中,你只有PartyFactory而没有ifswitch语句,但是一个人聚会和一个公司聚会是完全不同的。

答案 1 :(得分:0)

为了避免在访问FullName元素时出现NullReferenceException,您可以将其强制转换为字符串,而无需在元素上调用Value。如果不存在,则返回null,否则返回该值。然后,您可以在迭代结果时检查null。

更改:FullName = party.Element("FullName").Value,

收件人:FullName = (string)party.Element("FullName"),

更新的查询将是:

var partyElements = from party in xmlDoc.Descendants("Party")
    select new
    {
        Name = party.Attribute("id").Value,
        PartyTypeCode = party.Element("PartyTypeCode").Value,
        FullName = (string)party.Element("FullName"),
        GovtID = party.Element("GovtID").Value,
    };

对于某些项目可能存在或可能不存在的所有元素,您可以执行相同的操作。

答案 2 :(得分:0)

我觉得艾哈迈德的解决方案是要走的路。但这是我提出的黑客攻击。如果'FullName'是两个不同类型的聚会节点之间唯一的区别元素,那么我猜以下可能有效:

var validParty = xElement.Descendants("Party")
                            .Elements().Where(x => x.Name == "FullName")
                            .Ancestors("Party")
                            .Elements().Where(x => x.Name == "PartyTypeCode")
                            .Ancestors("Party");


 var partyElements = from party in validParty 
            select new
            {
                Name = party.Attribute("id").Value,
                PartyTypeCode = party.Element("PartyTypeCode").Value,
                FullName = party.Element("FullName").Value,
                GovtID = party.Element("GovtID").Value,
            }; 

您可以添加其他区分节点(如“PartyTypeCode”)。我不确定这方面的表现方面。