Search code examples
c#xmlxmlreader

XmlReader.HasAttributes returns false immediately after creation


I'm relatively new to using C#'s XML classes. I can't even get an XML reader to recognize that the string I'm passing to it is XML. Here is my unit test which I'm using to test basic Xml reading

[TestFixture()]
public class LegacyWallTests
{
    [Test()]
    public void ReadLegacyWallFile()
    {
        var legacyWallText = legacyfiles.legacywall1;
        {
            string xmlString = legacyfiles.legacywall1;
            using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
            {
                reader.HasAttributes.Should().BeTrue();
            }
        }
    }
}

And here is the XML I'm trying to read

<Wall>
  <Actual>
    <Specifications>
      <Insertion> 375.6858 916.8871 0.0000 </Insertion>
      <Angle> 3.14159 </Angle>
      <WallDesc> E4-1, H: 8' 1 1/8, Sh: Yes, S: 2~4~2~9-0-0~SPF~~, Spc: Single @ 16 in OC, BP: 2~4~2~12-0-0~SYP~~, CP: 2~4~2~12-0-0~SYP~~, TP: 2~4~2~12-0-0~SYP~~,\P LI: Single @ 38.75000000, CB: No, VB: No, NCT: 2~4~2~9-0-0~SPF~~, CT: 2~4~2~9-0-0~SPF~~, Pac: 2~4~2~9-0-0~SPF~~, Mir: Yes </WallDesc>
      <WallNum> 1 </WallNum>
      <VaporBarrier></VaporBarrier>
    </Specifications>
  </Actual>
</Wall>

legacyfiles.legacywall1 is the name of the xml file I added to my project's resources. I know that the xml file is being read because outputting that string to the console gives me the xml from the file. However, when I create the XmlReader and test that there are attributes it says there aren't any. I don't know what I'm doing wrong.


Solution

  • XmlReader.HasAttribute returns true if the current node has attributes. As you don't advance into the document, the reader starts at the root element, <Wall>, which doesn't have attributes. Nor do any other of your elements.

    An attribute is bar in <foo bar="baz" />.

    You also generally don't want to mess with XML using readers. Obtain or generate an XSD (also very useful for input validation), generate a class from that XSD and deserialize the incoming XML to an instance of that class. Then you can just access wall.Actual.Specifications[0].WallDesc.