1

Have the following code, new to this so be kind, it looks clunky and isn't returning what I expect it to return. Basically I'm trying to read nodes for Operator, Password, and Group values into vars and return via a tuple.

public static Tuple<string, string, string> ReadSecurity()
{            
    XmlReader reader = XmlReader.Create("Operator.xml");
    string sOperator = "";
    string sPassword = "";
    string sGroup = "";

    while (reader.Read())
    {
        if(reader.NodeType == XmlNodeType.Element && reader.Name == "Security")
        {
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                reader.Read();
                if (reader.NodeType == XmlNodeType.Text)
                {
                    sOperator = reader.Value;
                }

                reader.Read();
                if (reader.NodeType == XmlNodeType.Text)
                {
                    sPassword = reader.Value;
                }

                reader.Read();
                if (reader.NodeType == XmlNodeType.Text)
                {
                    sGroup = reader.Value;
                }
            }
        }
    }
    return Tuple.Create(sOperator, sPassword, sGroup);
}

Seem to be missing the first value each time but have no idea how to change this, online tutorials are assuming a lot more knowledge than I currently have.

For example:
See below for the current iteration (yes, I know the password should be encrypted).

<?xml version="1.0" encoding="utf-8"?> 
<Security ver="beta"> 
    <Operator>Ted</Operator> 
    <Password>password</Password> 
    <Group>op</Group> 
</Security>
zx485
  • 28,498
  • 28
  • 50
  • 59
ScaryMinds
  • 335
  • 3
  • 11
  • Show us an xml example. – Alexander Petrov Mar 23 '18 at 00:08
  • In the future please add additional information as edits to the question and not as comments. – zx485 Mar 23 '18 at 00:22
  • Need a few samples of the operator and password if they are in the same file. – jdweng Mar 23 '18 at 01:32
  • 2
    It's going to be **much much easier** to stream through the file, find each `` elements, and them with `XElement.ReadFrom()`. See e.g. [How to read large xml file without loading it in memory and using XElement](https://stackoverflow.com/a/18282052) and [Get the EndElement Node of an XElement](https://stackoverflow.com/a/40070665). – dbc Mar 23 '18 at 01:39
  • Side note: "...the password should be encrypted" is awful practice for most cases, especially for implementing homemade authentication... but you probably also know it already. – Alexei Levenkov Mar 23 '18 at 02:40
  • Unless the XML you're reading is huge (which looks unlikely), I'd suggest you use LINQ to XML rather than `XmlReader`. This is very low-level stuff that's fiddly to write, resulting in issues like this. – Charles Mager Mar 23 '18 at 08:03

1 Answers1

1

Put a breakpoint at the beginning of your method and run it step by step pressing F11. You will see that the XmlReader reads, among others, the Whitespace nodes. See Debug > Windows > Autos or Locals window.

You must ignore these Whitespace nodes and correctly navigate to nodes of type Text, to read their values. You also need to correctly handle start and end tags.

As a result, the code might look like this:

using (var reader = XmlReader.Create("Operator.xml"))
{
    string sOperator = "";
    string sPassword = "";
    string sGroup = "";

    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Operator")
        {
            reader.Read(); // move to Text node
            sOperator = reader.Value;
        }

        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Password")
        {
            reader.Read(); // move to Text node
            sPassword = reader.Value;
        }

        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Group")
        {
            reader.Read(); // move to Text node
            sGroup = reader.Value;
        }
    }

    return Tuple.Create(sOperator, sPassword, sGroup);
}

However the XmlReader class has many useful methods. If you use them correctly, you can make its use simple and enjoyable.

using (var reader = XmlReader.Create("Operator.xml"))
{
    reader.ReadToFollowing("Operator");
    var sOperator = reader.ReadElementContentAsString();

    reader.ReadToFollowing("Password");
    var sPassword = reader.ReadElementContentAsString();

    reader.ReadToFollowing("Group");
    var sGroup = reader.ReadElementContentAsString();

    return Tuple.Create(sOperator, sPassword, sGroup);
}
Alexander Petrov
  • 13,457
  • 2
  • 20
  • 49