如何为此 Linq to XML 函数编写 Lambda 语句?
我正在使用 此 XSD 文件。 与以下内容相关的 XML 部分这个问题在这里:
<?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>
要获取给定 xs:element
的 documentation
值,我有这个小函数,它递归地遍历后代节点,直到找到 Documentation
元素:
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 "";
}
到目前为止一切顺利。单元测试如下所示:
[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);
}
哪个通过。现在我想通过添加额外的情况来扩展测试,如下所示:
XElement z = elements.DescendantsAndSelf()
.First(y => y.Attribute("name")
.ToString().Contains("ProgramName"));
actual = target.GetCode(z);
Assert.AreEqual("PN", actual);
...但是由于空对象引用而失败(很可能y.Attribute("name")< /代码>)。
您看到我评论的上面函数中的循环了吗?
// I'll explain this loop in a moment.
foreach (var t in s.Elements())
{
if (t.Name.ToString().Contains("documentation"))
return t.Value;
}
之所以这样写,是因为我不知道如何在有效的 Lambda 语句中表达条件。
有什么建议吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您需要使用命名空间:
You need to use namespaces:
试试这个
Try this
您的问题是
y.Attribute("name").ToString().Contains("ProgramName")
在每个不包含“name”属性的元素上都会失败。您需要这样的东西:如果您希望所有
元素都包含name
属性,您可以忽略 null 检查并执行以下操作:编辑:请注意,我添加了扩展名称以包含命名空间 URL。看看是否有效。
Your problem is that
y.Attribute("name").ToString().Contains("ProgramName")
will fail on every element that doesn't contain a "name" attribute. You need something like this:If you expect all
<element>
elements to contain aname
attribute, you can ignore the null check and do this:EDIT: Note that I added the expanded name to include the namespace URL. See if that works.
这是有效的代码。
请注意
DescendantsAndSelf()
调用中对GetName()
方法的调用。这将返回格式正确、以 URI 为前缀的名称,格式为{http://www.w3.org/2001/XMLSchema}element
,它将与xs:element
正确匹配代码>名称。结果是,
DescendantsAndSelf()
仅返回那些名为xs:element
的元素,所有这些元素都具有与其关联的属性(因此不可能出现空引用)引用Attributes
集合时出错)。Here is the code that works.
Notice the call to the
GetName()
method in theDescendantsAndSelf()
call. This returns a properly formatted URI-prefixed name of the form{http://www.w3.org/2001/XMLSchema}element
, which will match correctly to thexs:element
names.The result is that
DescendantsAndSelf()
returns only those elements having the namexs:element
, all of which have attributes associated with them (so there is no chance of a null reference error when referencing theAttributes
collection).