在C#中查找XML节点忽略其余部分

时间:2013-04-07 21:34:50

标签: c# xml

我有一个非常难看的APP,它从我的PC读取串口,连接到这个串口的设备将XML数据发送到这个APP ... 我的应用程序将XML数据读取为字符串并在节点<watts>中查找变量,但是一旦设备发送不同的XML数据(历史数据),我的应用程序将使用该信息崩溃,因为它找不到节点<watts>。 我只想检查节点是否存在并忽略不正确的数据。 数据来自串行端口到名为XMLData的字符串......

正确的数据:

<msg>
    <src>CC128-v1.34</src>
    <dsb>00030</dsb>
    <time>21:01:59</time>
    <tmpr>18.4</tmpr>
    <sensor>0</sensor>
    <id>00077</id>
    <type>1</type>
    <ch1>
        <watts>00366</watts>
    </ch1>
</msg>

数据不正确:

<msg>
    <src>CC128-v1.34</src>
    <dsb>00030</dsb>
    <time>21:02:00</time>
    <hist>
        <dsw>00030</dsw>
        <type>1</type>
        <units>kwhr</units>
        <data>
            <sensor>0</sensor>
            <h650>0.856</h650>
            <h648>1.418</h648>
            <h646>0.765</h646>
            <h644>0.742</h644>
        </data>
        <data>
            <sensor>1</sensor>
            <h650>0.000</h650>
            <h648>0.000</h648>
            <h646>0.000</h646>
            <h644>0.000</h644>
        </data>
        <data>
            <sensor>2</sensor>
            <h650>0.000</h650>
            <h648>0.000</h648>
            <h646>0.000</h646>
            <h644>0.000</h644>
        </data>
    </hist>
</msg>

3 个答案:

答案 0 :(得分:1)

您可以使用LINQ to XML:

var doc = XDocument.Parse(yourXMLString);

var watts = doc.Descendants("watts").Select(x => (string)x).FirstOrDefault();

if (watts == null)
{
    // incorrect
}
else
{
    // correct
}

它将watts节点内容作为字符串。当<watts>出现多次时,会选择第一个。

答案 1 :(得分:0)

您可以尝试使用XmlTextReader - 它可以让您根据需要从文件中读取尽可能多的行,这样即使您的文件不正确,您也可能获得正确的结果XML文档:

var stream = new StreamReader("Input.txt");
string watts = null;

using (var reader = new XmlTextReader(stream))
{
    while (reader.Read())
    {
        if (reader.IsStartElement("watts"))
        {
            reader.Read();
            watts = reader.Value;
            break;
        }
    }
}

答案 2 :(得分:0)

对于这么简单的事情,你可以看一下使用正则表达式。我知道,我知道,使用带有html / xml的正则表达式是"succumbing to the temptations of the dark god Cthulu",但这只是提取一个,也许是多个值,所以我不知道它是怎么回事做任何伤害。

另外,它会跳过你得到的那些时髦的错误,因为它没有读取/解析xml。它可以像你想要的一样无效。

掀起一个可能的正则表达式:

Regex regex = new Regex("<watts>(?<match>[0-9]+)</watts>");

MatchCollection matches = regex.Matches(sample);

foreach (Match match in matches)
{
    Console.WriteLine(match.Groups["match"].Value);
}

以下是正则表达式的细分,以防你(或其他任何人在将来遇到这种情况)不熟悉它们:

  • <watts>匹配开始标记
  • (?<match>[0-9]+)表示一个命名的捕获组,匹配的字符串将存储在match.Groups中,索引为match
  • [0-9]+当然是瓦特标签中的值。在这种情况下,只有数字,至少有一个(您可以在?之后添加+以使其不贪婪,但我不确定是否/如何有帮助<) / LI>
  • </watts>与结束标记
  • 匹配
  • .Matches方法返回示例字符串
  • 中的所有实例

我无法在错误的代码中注意到watts标记丢失。这只是你的疏忽吗?你总是可以这样做,以便正则表达式不仅匹配瓦特,而且还匹配在不正确的数据中替换它的其他标签。

作为旁注,我不建议使用正则表达式来代替完整的xml读取器/解析器。但是从文档中获取几个值似乎有点过分了。