从XML文件中选择前n个

时间:2012-11-11 08:43:12

标签: c# xml linq

如何使用C#从下面的ContractID为2的xml文件中选择最后1个状态?

<actions>
     <Action>
    <ID>2</ID>
    <ContractID>1</ContractID>
    <EmployeeID>1</EmployeeID>
    <Date>2012-09-04 00:00:00.000</Date>
    <Reply/>
    <Status>4002</Status>
</Action>
    <Action>
    <ID>2</ID>
    <ContractID>2</ContractID>
    <EmployeeID>1</EmployeeID>
    <Date>2012-09-04 00:00:00.000</Date>
    <Reply/>
    <Status>4005</Status>
</Action>
    <Action>
    <ID>2</ID>
    <ContractID>2</ContractID>
    <EmployeeID>1</EmployeeID>
    <Date>2012-09-04 00:00:00.000</Date>
    <Reply/>
    <Status>4008</Status>
</Action>
</actions>

以及如何使用linq to xml或任何其他方式选择top n


和xml代码的linq是什么,它等同于以下的sql查询:

Select contracts.ID, contracts.ContractNo, 
    (select FieldName from tbl_SysType where ID =
    (select top 1 status from tbl_EmployeesActions where ContractID=contracts.ID and Status is not null order by ID desc ))as ContractStatus
from tbl_Contracts as contracts

如果存在名为Contracts.xml,SysType.xml和EmployeesActions.xml的xml文件,如下所示 Contracts.xml

<Contracts>
     <Contract>
    <ID>1</ID>
    <ContractNo>Mob124444</ContractNo>      
</Contract>
    <Contract>
    <ID>2</ID>
    <ContractNo>Mob124445</ContractNo>      
</Contract>
</Contracts>

EmployeesActions.xml

    <actions>
     <Action>
    <ID>2</ID>
    <ContractID>1</ContractID>
    <EmployeeID>1</EmployeeID>
    <Date>2012-09-04 00:00:00.000</Date>
    <Reply/>
    <Status>4002</Status>
</Action>
    <Action>
    <ID>2</ID>
    <ContractID>2</ContractID>
    <EmployeeID>1</EmployeeID>
    <Date>2012-09-04 00:00:00.000</Date>
    <Reply/>
    <Status>4005</Status>
</Action>
    <Action>
    <ID>2</ID>
    <ContractID>2</ContractID>
    <EmployeeID>1</EmployeeID>
    <Date>2012-09-04 00:00:00.000</Date>
    <Reply/>
    <Status>4008</Status>
</Action>
</actions>

Systype.xml

<SysTypes>
    <systype>
        <ID>4002</ID>
        <FieldName>New</FieldName>
    </systype>
<systype>
        <ID>4005</ID>
        <FieldName>Opened</FieldName>
    </systype>
<systype>
        <ID>4008</ID>
        <FieldName>Closed</FieldName>
    </systype>
</SysTypes>

2 个答案:

答案 0 :(得分:5)

以下是满足这两个要求的代码段:

XDocument doc = XDocument.Load(@"XMLFile.xml");

var statuses = doc.Descendants("Action")
                  .Where(s => s.Element("ContractID").Value.Equals("2"))
                  .Select(s => s.Element("Status").Value);

选择ContractID为2的最后状态

var lastStatus = statuses.Last();

选择ContractID为2的前N个状态

int N = 2; // assuming TOP 2
var topNStatuses = statuses.Take(N);

对于新要求,您可以使用此代码段替代SQL查询:

XDocument employees = XDocument.Load(@"EmployeesActions.xml");
XDocument contracts = XDocument.Load(@"Contracts.xml");
XDocument sysTypes = XDocument.Load(@"Systype.xml");

var result = employees.Descendants("Action")
            .Join(sysTypes.Descendants("systype"),
                e => e.Element("Status") != null ? e.Element("Status").Value : "",
                s => s.Element("ID").Value,
                (e, s) => new
                {
                    ID = e.Element("ID").Value,
                    ContractID = e.Element("ContractID").Value,
                    Status = s.Element("FieldName").Value
                })
            .Where(x => !String.IsNullOrEmpty(x.Status))
            .OrderByDescending(x => x.ID)
            .Take(1)
            .Join(contracts.Descendants("Contract"),
                e => e.ContractID,
                c => c.Element("ID").Value,
                (e, c) => new
                {
                    ContractID = c.Element("ID").Value,
                    ContractNo = c.Element("ContractNo").Value,
                    Status = e.Status
                });

答案 1 :(得分:4)

var result = XElement.Load("data.xml").
                      Descendants("Action").
                      Where(x => x.Element("ContractID").Value == "2")
                      .Select(y => new
                       {
                            id = y.Element("ID").Value,
                            empId = y.Element("EmployeeID").Value,
                            contractId = y.Element("ContractID").Value,
                            date = y.Element("Date").Value
                       });

选择前N(1)

var top = result.Take(1);

选择最后N(1)

var last = result.Skip(result.Count()-1);