从XML文件中选择前n个

Heb*_*dly 2 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>
Run Code Online (Sandbox Code Playgroud)

以及如何使用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
Run Code Online (Sandbox Code Playgroud)

如果有包含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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

Fur*_*dar 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);
Run Code Online (Sandbox Code Playgroud)

选择ContractID为2的最后状态

var lastStatus = statuses.Last();
Run Code Online (Sandbox Code Playgroud)

选择前N个状态,其中ContractID为2

int N = 2; // assuming TOP 2
var topNStatuses = statuses.Take(N);
Run Code Online (Sandbox Code Playgroud)

对于新要求,您可以使用此代码段替代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
                });
Run Code Online (Sandbox Code Playgroud)