从多个父节点收集XML子节点

时间:2015-06-13 18:10:51

标签: c# xml

我正在为我正在撰写的个人计划进行一些网络浪费时间。用户输入端口/位置代码,然后从UKHO为该特定端口下载包含下一个七天的表格格式的潮汐时间的HTML网页。然后程序删除表之前和之后的所有HTML代码,留下包含潮汐数据的七个表。然后它将HTML转换为有效的XML文件。这是程序为端口创建的XML:

<?xml version="1.0" encoding="utf-8"?>
<Tides portID="0547" port="St. Ives">
  <Day>
    <tr>
      <th>Sat 13 Jun</th>
    </tr>
    <tr>
      <th>HW</th>
      <th>LW</th>
      <th>HW</th>
      <th>LW</th>
    </tr>
    <tr>
      <td>02:00</td>
      <td>08:35</td>
      <td>14:30</td>
      <td>21:05</td>
    </tr>
    <tr>
      <td>5.9m</td>
      <td>1.4m</td>
      <td>5.9m</td>
      <td>1.4m</td>
    </tr>
  </Day>
  <Day>
    <tr>
      <th>Wed 17 Jun</th>
    </tr>
    <tr>
      <th>HW</th>
      <th>LW</th>
      <th>HW</th>
    </tr>
    <tr>
      <td>05:17</td>
      <td>11:40</td>
      <td>17:34</td>
    </tr>
    <tr>
      <td>6.4m</td>
      <td>1.0m</td>
      <td>6.5m</td>
    </tr>
  </Day>
  <Day>
    <tr>
      <th>Sun 14 Jun</th>
    </tr>
    <tr>
      <th>HW</th>
      <th>LW</th>
      <th>HW</th>
      <th>LW</th>
    </tr>
    <tr>
      <td>02:57</td>
      <td>09:29</td>
      <td>15:23</td>
      <td>21:56</td>
    </tr>
    <tr>
      <td>6.1m</td>
      <td>1.2m</td>
      <td>6.1m</td>
      <td>1.2m</td>
    </tr>
  </Day>
</Tides>

但是我需要将其转换为如下格式:

<?xml version="1.0" encoding="utf-8"?>
<Tides portID="0547" port="St. Ives">
  <Day date="Sat 13 Jun">
    <Tides>
      <Tide type="HW" time="02:00" height="5.9m"/>
      <Tide type="LW" time="08:35" height="1.4m"/>
      <Tide type="HW" time="14:30" height="5.9m"/>
      <Tide type="LW" time="21:05" height="1.4m"/>
    </Tides>
  </Day>
  <Day date="Wed 17 Jun">
    <Tides>
      <Tide type="HW" time="05:17" height="6.4m"/>
      <Tide type="LW" time="11:40" height="1.0m"/>
      <Tide type="HW" time="17:34" height="6.5m"/>
    </Tides>
  </Day>
  <Day date="Sun 14 Jun">
    <Tides>
      <Tide type="HW" time="02:57" height="6.1m"/>
      <Tide type="LW" time="09:29" height="1.2m"/>
      <Tide type="HW" time="15:23" height="6.1m"/>
      <Tide type="LW" time="21:56" height="1.2m"/>
    </Tides>
  </Day>
</Tides>

我不知道从哪里开始将其转换为这样的格式,主要是因为代码是行而不是列(即每个标记包含列而不是行)所以我不得不以某种方式计算每个迭代从每个标记获取一个节点,并以新格式将其添加到单个节点,但我无法弄清楚如何执行此操作。事实上,有一天可以包含4,3或2次潮汐(显示为样本中的第二个标记)。

我需要新格式,因此它是一个较小的文件,更容易阅读。如何使用C#将第一种格式的XML转换为第二个XML样本的格式?感谢您提供给我的任何帮助,我无法解决如何将子HW / LW,时间和高度收集到包含其中一个的集合中并将它们放入新节点中。

1 个答案:

答案 0 :(得分:0)

这不是代码编写服务,但我似乎感觉有点慷慨。您希望使用LINQ to XML进行解析,然后将数据转换为所需的格式。此代码不处理源文件中的任何问题(例如,如果每个<tr>包含不同数量的<td>值),但它适用于您的示例:

var doc = XDocument.Parse(xml);

foreach (var day in doc.Descendants("Day"))
{
    var rows = day.Elements("tr").ToList();

    rows.Remove();

    var date = (string)rows[0].Element("th");

    day.Add(new XAttribute("date", date));

    var tides = new XElement("Tides");

    var types = rows[1].Elements().Select(e => e.Value).ToArray();
    var times = rows[2].Elements().Select(e => e.Value).ToArray();
    var heights = rows[3].Elements().Select(e => e.Value).ToArray();

    for (var i = 0; i < types.Length; i++)
    {
        tides.Add(new XElement("Tide",
            new XAttribute("type", types[i]),
            new XAttribute("time", times[i]),
            new XAttribute("height", heights[i])
            ));
    }

    day.Add(tides);
}

var result = doc.ToString();