0

私はLinqを理解しようとしているだけで、非常に単純に見えることをしようとしていますが、思い通りに出力することはできません。私は何日もの間、さまざまな方法を試してみましたが、うまくいきませんでした。

だから私はクラスEarObsを持っています、それはメンバーを持っています:eventID、icaoId、frm、sta、db。

リストから XML ドキュメントを作成しようとしています。XML ドキュメントを次のようにしたい:

<EarObs EventId = "123456789">
    <icao icaoID = "0001">
        <frm frm = "01">
            <sta sta = "00">
                <db>87</db>
                <hz>99</hz>
            </sta>
            <sta station = "01">
                <db>79</db>
                <hz>99</hz>
            </sta>
        </frm>
        <frm frm = "02">
        ................
        </frm>
    </icao>
</EarObs>

そして、これは、複数のフレームまたは複数のコードなどがある場合、同じ順序を維持しながらずっと続きます.

だから、これは私が最近試したことですが、それでも私が望むように出力されません.Obsが繰り返され、どこが間違っているのかわかりません.

string eventGUID = "eventGUID";

List<EarObs> frameObsList = new List<EarObs>();
for (int frm = 2; frm > 0; frm--)
{
    for (int sta = 5; sta > 0; sta--)
    {
        frameObsList.Add(new EarObs("KAPF", eventGUID, frm, sta, 85 + sta, 99 + sta));
        cnt++;
    }

}
String eventID = obsList.First().EventGUID;

List<EarObs> distinctApts =
    obsList
    .GroupBy(p => p.IcaoId)
    .Select(g => g.First())
    .ToList();


XElement xElement = new XElement("EarObs", new XAttribute("eventID", eventID),

    from ea in distinctApts
    orderby ea.IcaoId
    select new XElement("icao", new XAttribute("code", ea.IcaoId),
        from eb in obsList
        where ea.IcaoId == eb.IcaoId
        orderby eb.Frm
        select new XElement("frm", new XAttribute("frm", eb.Frm),
            from ec in obsList                 
            where eb.Frm == ec.Frm
            orderby ec.Sta
            select  new XElement("sta", new XAttribute("sta", ec.Sta),
                new XElement("db", ec.Db),
                new XElement("hz", ec.Hz)))));

このコードを使用して、ステーションごとに 1 回フレームを繰り返す xml ドキュメントを取得します。これは正しくありません。これは順番に簡単に実行できるように感じますが、学習しようとしていますが、これは非常に単純なので、Linqで実行できるはずです。リスト内の各要素が XML ドキュメントで一度だけ表されるようにする必要があります。どうすればいいですか?

また、複数の eventId も処理できるように拡張したいと考えていますが、それは XML 構造を正しくすることほど重要ではありません。linq を使用した要素のフィルタリングを含む XML を作成する例をあまり多く見つけることができませんでした。ほとんどの例では、XML を作成する前にリストがすべて構造化されているようです。

4

2 に答える 2

1

カスタムクラスがあるので、EarObsはオブジェクトにXml属性を定義し、XmlSerlizerクラスを使用してオブジェクトをシリアル化してみませんか?このようにして、オブジェクトでLinqを引き続き使用し、オブジェクトを出力することもできます。

例:以下はチームで、プレーヤーがいます。

[XmlRoot("root")]
public class Team
{
    private List<Player> players = new List<Player>();

    [XmlElement("player")]
    public List<Player> Players { get { return this.players; } set { this.players = value; } }

    // serializer requires a parameterless constructor class
    public Team() { }
}

public class Player
{
    private List<int> verticalLeaps = new List<int>();

    [XmlElement]
    public string FirstName { get; set; }
    [XmlElement]
    public string LastName { get; set; }
    [XmlElement]
    public List<int> vertLeap { get { return this.verticalLeaps; } set { this.verticalLeaps = value; } }

    // serializer requires a parameterless constructor class
    public Player() { }
}

何人かのプレーヤーがいるチームを作成したら、次のことを行う必要があります。

Team myTeamData = new Team();
// add some players on it.
XmlSerializer deserializer = new XmlSerializer(typeof(Team));
using (TextReader textReader = new StreamReader(@"C:\temp\temp.txt"))
{
    myTeamData = (Team)deserializer.Deserialize(textReader);
    textReader.Close();
}

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

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <player>
    <FirstName>dwight</FirstName>
    <LastName>howard</LastName>
    <vertLeap>1</vertLeap>
    <vertLeap>2</vertLeap>
    <vertLeap>3</vertLeap>
  </player>
  <player>
    <FirstName>dwight</FirstName>
    <LastName>howard</LastName>
    <vertLeap>1</vertLeap>
  </player>
</root>
于 2013-02-15T20:15:47.290 に答える
0

最も簡単な方法は、直列化を処理する一連のクラスを作成することです。

public class sta
{
    public int db { get; set; }
    public int hz { get; set; }

    [XmlAttribute()]
    public string station { get; set; }
}

public class frm
{
    [XmlAttribute("frm")]
    public string frmID { get; set; }

    [XmlElement("sta")]
    public List<sta> stas { get; set; }
}

public class icao
{
    [XmlAttribute]
    public string icaoID { get; set; }

    [XmlElement("frm")]
    public List<frm> frms { get; set; }
}

public class EarObs
{
    [XmlAttribute]
    public string EventId { get; set; }

    [XmlElement("icao")]
    public List<icao> icaos { get; set; }
}

また、xmlシリアライザーを使用してシリアライズ/デシリアライズできます。以下は、あなたが持っているものと同じ構造にシリアライズされます。

XmlSerializer serializer = new XmlSerializer(typeof(EarObs));
EarObs obs = new EarObs() { EventId = "123456789" };
obs.icaos = new List<icao>();
obs.icaos.Add(new icao() { icaoID = "0001" });
obs.icaos[0].frms = new List<frm>();
obs.icaos[0].frms.Add(new frm() { frmID = "01" });
obs.icaos[0].frms[0].stas = new List<sta>();
obs.icaos[0].frms[0].stas.Add(new sta() { station = "00", db = 87, hz = 99 });
obs.icaos[0].frms[0].stas.Add(new sta() { station = "01", db = 79, hz = 99 });
obs.icaos[0].frms.Add(new frm() { frmID = "02" });

using (StringWriter s = new StringWriter())
{
    serializer.Serialize(s, obs);
    string test = s.ToString();
}

出力;

<?xml version="1.0" encoding="utf-16"?>
<EarObs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" EventId="123456789">
  <icao icaoID="0001">
    <frm frm="01">
      <sta station="00">
        <db>87</db>
        <hz>99</hz>
      </sta>
      <sta station="01">
        <db>79</db>
        <hz>99</hz>
      </sta>
    </frm>
    <frm frm="02" />
  </icao>
</EarObs>

さて、これはかなり面倒に思えますが、xsd.exe ツール (私が信じているフレームワークに付属しています) を使用して、特定の xml ファイルに一致する一連のクラスを自動的に作成することができます。中間の xsd ファイル (痛みはありません)。ここで方法を見つけることができます。xsd から .NET 4.0 クラスを生成するには?

于 2013-02-15T20:31:49.473 に答える