I am working with this XSD file. The portion of the XML that is relevant to this question is here:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="https://wsmrc2vger.wsmr.army.mil/rcc/manuals/106-11"
targetNamespace="https://wsmrc2vger.wsmr.army.mil/rcc/manuals/106-11"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="Tmats">
<xs:complexType>
<xs:sequence>
<xs:annotation>
<xs:documentation>TMATS G Group</xs:documentation>
</xs:annotation>
<xs:element name="ProgramName" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>PN</xs:documentation>
</xs:annotation>
</xs:element>
To get the documentation
value for a given xs:element
, I have this small function, which recursively walks the descendant nodes until it finds the documentation
element:
public string GetCode(XElement e)
{
foreach (var s in e.Elements())
{
// If we hit an intervening element, bail out.
if (s.Name.ToString().Contains("element"))
return "";
if (s.Name.ToString().Contains("annotation"))
{
// I'll explain this loop in a moment.
foreach (var t in s.Elements())
{
if (t.Name.ToString().Contains("documentation"))
return t.Value;
}
}
else
return GetCode(s);
}
return "";
}
So far so good. The unit test looks like this:
[TestMethod()]
public void GetCodeTest()
{
string path = @"C:\Documents and Settings\harvey robert\Desktop\Tmats.xsd";
IEnumerable<XElement> elements =
from e in XElement.Load(path).Elements()
select e;
TmatsDictionary target = new TmatsDictionary();
XElement x = elements.First();
string actual = target.GetCode(x);
Assert.AreEqual("TMATS G Group", actual);
}
Which passes. Now I want to extend the test by adding an additional case, like this:
XElement z = elements.DescendantsAndSelf()
.First(y => y.Attribute("name")
.ToString().Contains("ProgramName"));
actual = target.GetCode(z);
Assert.AreEqual("PN", actual);
...But this fails due to a null object reference (most likely y.Attribute("name")
).
Did you see the loop in the function above that I commented?
// I'll explain this loop in a moment.
foreach (var t in s.Elements())
{
if (t.Name.ToString().Contains("documentation"))
return t.Value;
}
It's written that way because I can't figure out how to express the condition in a Lambda statement that works.
Any suggestions?