1

私はこのようなネストされたxmlを持っています。

 < H>

   < FP >
       < Name="FP1"/>

       < R >
       < Name = "R1"/> 

            < O>
            < Name="O1"/>
            < /O>
            < O>
                < Name="O2"/>
            < /O>
     < /R>       
     < R>
     < Name = "R2"/>
         < O>
    < Name="O4"/>
          < /O>
     < /R>
< /FP>

< FP>
    < Name="FP2" />

    < R>
          < Name = "R3"/>

          < O>
             < Name="O5"/>
          < /O>
          < O>
             < Name="O6"/>
          < /O>
    < /R>
< /FP>

   < R> 
       < Name="R4"/>
       < O>
    < Name="O7"/>
   < /O>
        < O>
            < Name="O8"/>
        < /O>
     < /R>
 < R>
     < Name="R5"/>
     < O >
          < Name="O9"/>
     < /O>
  < /R>

< /H>

このxmlを読み取るためにデシリアライゼーションを使用しています。

ここに私の逆シリアル化クラスがあります:

[XmlRoot("H")]
public class ReplyH
{
    [XmlElement("FP")]
    public List<ReplyFP> FPs;

    [XmlElement("R")]
    public List<ReplyR> Rs;

}

public class ReplyFP
{
    [XmlElement("Name")]
    public string Name;

    [XmlElement("R")]
    public List<ReplyR> Rs = new List<ReplyR>();
}


public class ReplyR
{
    [XmlElement("Name")]
    public string Name;

    [XmlElement("O")]
    public List<ReplyO> Os = new List<ReplyO>();
}


public class ReplyO
{
    [XmlElement("Name")]
    public string Name;
}

O タグを繰り返し処理する必要があります。

foreach(H.FP.RO の var O) や foreach(HRO の var O) のようなもの

1)。<O>上記のサンプルで < O> < Name = "O9" /> </O> . 2). I also need to get the parentR Name andFP Name if exists for a particularO`である最後のタグを見つける必要があります

linq/ラムダ式を使用してこれを取得するにはどうすればよいですか?

ありがとう

4

2 に答える 2

1

更新された質問に対して、Linq-to-objectsを使用して更新された回答。

コードはLinq-to-XMLの機能ほどエレガントではありませんが、機能します。

ノート

  1. FPとRはトップレベルで異なるコレクションにあるため、ソースXMLのようにドキュメントの順序を知る方法はありません。コードが示すように、 Rは内部のFPに従うと想定してReplyHいます(サンプルXMLも示唆しているようです)。
  2. 使用するシリアル化クラスを修正する必要がありました

    [XmlAttribute("Name")] public string Name;
    

    それが(偶然に?)XmlElement("Name")あなたの質問で言ったところ

using System.Collections.Generic;
using System.Xml.Serialization;
using System.Linq;
using System.IO;
using System;

public class Program
{
    public static void Main(string[] args)
    {
        ReplyH doc;
        using (var reader = new StringReader(xml))
            doc = (ReplyH) new XmlSerializer(typeof(ReplyH)).Deserialize(reader);

        var Rs = doc.FPs
            .SelectMany(fp => fp.Rs.Select(r => new { Parent = fp            , R=r }))
            .Concat    (     doc.Rs.Select(r => new { Parent = (ReplyFP) null, R=r }));

        var Os = Rs.SelectMany(r => r.R.Os.Select(o => new { Parent = r, O=o }));

        var lastO = Os.Last();
        Console.WriteLine(lastO.O.Name);

        if (lastO != null)
        {
            Console.WriteLine("Parent R has name '{0}'", lastO.Parent.R.Name);

            ReplyFP granddad = lastO.Parent.Parent;
            if (granddad != null)
                Console.WriteLine("Parent FP has name '{0}'", granddad.Name);
        }
    }

    const string xml = @"<H>
        <FP Name=""FP1"">
            <R Name=""R1""> 
                <O Name=""O1""/>
                <O Name=""O2""/>
            </R>       
            <R Name=""R2"">
                <O Name=""O4""/>
            </R>
        </FP>
        <FP Name=""FP2"">
            <R Name=""R3"">
                <O Name=""O5""/>
                <O Name=""O6""/>
            </R>
        </FP>
    <!--
        <R Name=""R4"">
            <O Name=""O7""/>
            <O Name=""O8""/>
        </R>
        <R Name=""R5"">
            <O Name=""O9""/>
        </R>
    -->
        </H>";
}

[XmlRoot("H")] public class ReplyH {
    [XmlElement("FP")] public List<ReplyFP> FPs = new List<ReplyFP>();
    [XmlElement("R")] public List<ReplyR> Rs = new List<ReplyR>();
}

public class ReplyFP {
    [XmlAttribute("Name")] public string Name; 
    [XmlElement("R")] public List<ReplyR> Rs = new List<ReplyR>();
}

public class ReplyR {
    [XmlAttribute("Name")] public string Name; 
    [XmlElement("O")] public List<ReplyO> Os = new List<ReplyO>();
}

public class ReplyO {
    [XmlAttribute("Name")] public string Name;
}

出力:

O6
Parent R has name 'R3'
Parent FP has name 'FP2'

または、XMLの最後のブロックのコメントを解除した後:

O9
Parent R has name 'R5'
于 2012-10-30T00:15:59.883 に答える
1

ここでは Xml.Linq を使用しています:更新更新された質問に対する競合する回答も参照してください

using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
using System;

public class stuff
{
    public static void Main(string[] args)
    {
        var doc = XDocument.Parse(xml);

        var last = doc.Root
            .XPathSelectElements("//H/FP/R/O | //H/R/O")
            .Last();

        Console.WriteLine(last);
        Console.WriteLine("Parent R has name '{0}'", last.Parent.Attribute("Name").Value);

        var granddad = last.Parent.Parent;
        if (granddad.Name == "FP")
            Console.WriteLine("Parent FP has name '{0}'", granddad.Attribute("Name").Value);
    }

    const string xml = @"<H>
        <FP Name=""FP1"">
            <R Name=""R1""> 
                <O Name=""O1""/>
                <O Name=""O2""/>
            </R>       
            <R Name=""R2"">
                <O Name=""O4""/>
            </R>
        </FP>
        <FP Name=""FP2"">
            <R Name=""R3"">
                <O Name=""O5""/>
                <O Name=""O6""/>
            </R>
        </FP>
    <!--
        <R Name=""R4"">
            <O Name=""O7""/>
            <O Name=""O8""/>
        </R>
        <R Name=""R5"">
            <O Name=""O9""/>
        </R>
    -->
        </H>";
}

出力

<O Name="O6" />
Parent R has name 'R3'
Parent FP has name 'FP2'

XML の最後のセクションのコメントを外すと、次のようになります。

<!--
    <R Name=""R4"">
        <O Name=""O7""/>
        <O Name=""O8""/>
    </R>
    <R Name=""R5"">
        <O Name=""O9""/>
    </R>
-->

出力は次のようになります。

<O Name="O9" />
Parent R has name 'R5'
于 2012-10-29T23:38:32.630 に答える