Search code examples
c#filestreamxmltextreader

Using XmlTextReader to read attributes from element


In the code below, I'm finding the "Undly" element and then setting the appropriate attributes to a class. Is that the correct way to do it? Or should I be creating a new XElement class and then finding the attributes?

I'm still learning about the XMLTextReader and would like to use the best practices.

Also, I'm not sure if I should use the constructor that accepts the string (file path) to the XML file or use the constructor that uses the filestream. It seemed like using the filestream had a faster performance.

Here is the code

using (var fs = new FileStream(RBMRBHTheoretical, FileMode.Open, FileAccess.Read))
{
    using (var xmlReader = new XmlTextReader(fs))
    {
        while (xmlReader.Read())
        {
            if (xmlReader.NodeType == XmlNodeType.Element)
            {
                if (string.Equals(xmlReader.Name, "Undly"))
                {
                    occPLList.Add(new OccPL
                    {
                        Symbol = (string)xmlReader.GetAttribute("Sym").ToString().Trim(),
                        Description = (string)xmlReader.GetAttribute("Desc").ToString().Trim(),
                        Price = xmlReader.GetAttribute("Px") == null ? 0 : Convert.ToDecimal(xmlReader.GetAttribute("Px").ToString().Trim()),
                        Currency = (string)xmlReader.GetAttribute("Ccy").ToString().Trim()
                    });
                }
            }
        }
    } 
}

public class OccPL
{
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string Currency { get; set; }
    public string Symbol { get; set; }
}

Here is the xml file:

<FIXML r="20030618" s="20040109" v="4.4" xr="FIA" xv="1" xmlns="http://www.fixprotocol.org/FIXML-4-4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.fixprotocol.org/FIXML-4-4 https://optionsclearing.com/components/docs/membership/dds_ref/fia_1_1/fixml-main-4-4-FIA-1-1.xsd">
 <Batch>
   <SecList ListTyp="109" ListID="20175" BizDt="2017-12-07">
     <SecL Ccy="USD">
       <Instrmt Desc="iShares S&amp;P 100 ETF" SecTyp="OPT" SubTyp="ETO" Sym="OEF" Mult="100.0">
         <AID AltID="00013" AltIDSrc="RBHP"/>
       </Instrmt>
       <InstrmtExt>
        <Attrb Typ="101" Val="1.0000"/>
        <Attrb Typ="108" Val="1.0000"/>
       </InstrmtExt>
       <Undly Desc="iShares S&amp;P 100 ETF" Px="117.110000" Ccy="USD" Sym="OEF" ID="464287101" Src="1"/>
       <Stip Typ="RBHMIN" Val="2.500"/>
       <Stip Typ="CPMMIN" Val="3.750"/>
     </SecL>
    </SecList>
  </Batch>
 </FIXML>

Solution

  • Since you have an XSD for that XML in the FIXML element, I would probably generate a class from that XSD using the xsd.exe tool and deserialize to an instance of the generated class and pick out the bits you need for your own object. Deserializing XML to Objects in C#

    Going the deserialization route is performant but rigid. It will break if the XML doesn't match the schema. XmlTextReader and LINQ to XML are usually a bit slower but more flexible in what they can handle. If you're planning to handle a lot of arbitrary XML, what you're doing is fine. If your XML is going to have a well defined schema, don't waste your time writing a bunch of custom deserialization code when you can use the XSD to autogenerate everything you need and use the deserializer.