Reputation: 11
I have an very ugly APP done by me that reads serial port from my PC, the device attached to this serial port sends XML Data to this APP...
My app reads the XML data to a string and looks for variable in node <watts>
, but once a while the Device sends different XML Data(historic data), and my app with that information it crashes because it doesn't find the node <watts>
.
I only want to check if the node is there and ignore the incorrect data.
The data comes from the Serial Port to a String called XMLData...
Correct Data:
<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>
Incorrect data:
<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>
Upvotes: 1
Views: 173
Reputation: 2081
For something so simple, you could look at using a regex. I know, I know, using regular expressions with html/xml is "succumbing to the temptations of the dark god Cthulu", but this is just to extract one, maybe multiple, value(s), so I don't see how it'd do any harm.
Plus, it skips those funky errors you get because it doesn't read/parse xml. It can as invalid as you want it to be.
Whipped up a possible regex:
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);
}
Here's the breakdown on the regex, in case you're (or anyone else stumbling upon this in the future) unfamiliar with them:
<watts>
matches the opening tag(?<match>[0-9]+)
denotes a named capturing group, where the matched strings will be stored in match.Groups
with the index match
[0-9]+
is, of course, what the value in the watts tag will look like. In this case, only numbers, and at least one (you could add a ?
after the +
to make it non greedy, but I'm not sure if/how that will help)</watts>
matches the closing tag.Matches
method returns all instances in the sample stringI couldn't help noticing in the incorrect code that the watts
tag is missing. Is this just an oversight on your part? You could always make it so that the regex matches not only watts, but whatever other tag that replaces it in the incorrect data.
As a side note, I do not recommend the use of regular expressions as a replacement to a full blown xml reader/parser. But it seems like overkill to just grab a couple values out of a document.
Upvotes: 0
Reputation: 125650
You can try using XmlTextReader
- it will let you read as many lines from the file as necessary, so you may get correct results even when your file isn't correct XML document:
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;
}
}
}
Upvotes: 0
Reputation: 125650
You could use LINQ to XML:
var doc = XDocument.Parse(yourXMLString);
var watts = doc.Descendants("watts").Select(x => (string)x).FirstOrDefault();
if (watts == null)
{
// incorrect
}
else
{
// correct
}
It's getting watts
node content as a string. When there is more than one occurrence of <watts>
the first one is chosen.
Upvotes: 1