【问题标题】:Find XML node in C# ignore the rest在 C# 中查找 XML 节点忽略其余部分
【发布时间】:2013-04-08 08:34:49
【问题描述】:

我有一个非常丑陋的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>

【问题讨论】:

  • 请解释你为什么投反对票

标签: c# xml


【解决方案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 节点内容。当&lt;watts&gt; 出现不止一次时,将选择第一个。

【讨论】:

  • 您好,它给了我一直给我的相同错误:S 文件意外结束。以下元素未关闭:src、msg
  • 如果我打印出字符串,那不是不正确的...有什么方法可以忽略或查看正在发生的事情吗?
【解决方案2】:

您可以尝试使用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;
        }
    }
}

【讨论】:

  • 我认为问题在于 XML 来自串行端口,并且不知何故,它包含非法字符。现在它给出了错误:路径中的非法字符。
  • 我试过没有运气,我已经写入文件然后读取它... 文件意外结束。以下元素未关闭:src、msg xmldata = dataReceived; System.IO.File.WriteAllText(@path + "xml.txt", xmldata); var stream = new StreamReader(path + "xml.txt"); string wattsxml = null; using (var reader = new XmlTextReader(stream)) { while (reader.Read()) { if (reader.IsStartElement("watts")) { reader.Read(); break; } } }
【解决方案3】:

对于如此简单的事情,您可以考虑使用正则表达式。我知道,我知道,在 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);
}

以下是正则表达式的细分,以防您(或将来遇到此问题的其他人)不熟悉它们:

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

我不禁注意到watts 标记丢失的错误代码。这只是你的疏忽吗?您始终可以使正则表达式不仅匹配瓦特,而且匹配在不正确数据中替换它的任何其他标签。

附带说明,我不建议使用正则表达式来替代成熟的 xml 阅读器/解析器。但是从文档中获取几个值似乎有点过头了。

【讨论】:

    猜你喜欢
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多