1

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>
1
  • please give an explanation why you are voting down Commented Apr 7, 2013 at 21:45

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Hello, it is giving me the same error that has been giving me always :S Unexpected end of file has occurred. The following elements are not closed: src, msg
If i print out the string, that is not incorrect... Is that any way to ignore or to see what is happening?
0

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;
        }
    }
}

2 Comments

I think that the problem is that the XML is coming from Serial Port, and for somehow, it has illegal characters. Now it gives the error: Illegal characters in path.
I have tried with no Luck, i have written to a file and then reading it... Unexpected end of file has occurred. The following elements are not closed: 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; } } }
0

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
  • the .Matches method returns all instances in the sample string

I 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.