我正在尝试使用以下内容从XDocument中提取元素:
private bool ContainsEntity(FileInfo filePath, string entityType, int id, string field, string value)
{
try{
var doc = XDocument.Load(filePath.FullName);
var entities = doc.Descendants(entityType);
var ns = XNamespace.Get("http://schemas.sage.com/sdata/2008/1");
var attr = new XAttribute(ns + "uuid", id);
var specificEntities = entities.Where(y =>
{
var atts = y.Attributes();
return atts.Contains(attr);
});
return specificEntities.Any(ent =>
ent.Elements(field).Any(f => f.Value.Equals(value, StringComparison.OrdinalIgnoreCase)));
}catch{return false;}
}
xml文档中的相关元素如下所示:
<?xml version=""1.0"" encoding=""utf-8""?>
<feed xmlns=""http://www.w3.org/2005/Atom"" xmlns:sdata=""http://schemas.sage.com/sdata/2008/1"" xmlns:http=""http://schemas.sage.com/sdata/http/2008/1"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:mybi=""http://schemas.sage.com/mybi/import/2011"" xmlns:cs=""urn:cs"">
<author>
<name>Sage UK</name>
</author>
<category />
<generator version=""Sage Business Sync 1.0.0.0, Resources Package 0.1.0"" />
<id />
<title>Sage 200 UK Synchronization feed</title>
<mybi:contractVersion>1.2.5</mybi:contractVersion>
<mybi:resourceKind>depotStore</mybi:resourceKind>
<entry xmlns="""">
<author>
<name>Sage UK</name>
</author>
<id>1</id>
<title>operatingCompanyResource</title>
<updated>2014-12-19T10:32:43.501+00:00</updated>
<sdata:payload>
<depotStore sdata:uuid=""1"">
<operatingCompanyReference>1</operatingCompanyReference>
<originalType>
operatingCompanyWarehouse
</originalType>
<type>
operatingCompanyWarehouse
</type>
<name>warehouse1</name>
</depotStore>
</sdata:payload>
</entry>
</feed>";
问题是属性不匹配,因此specificEntities始终是零长度集合。问题似乎是属性名称的名称空间前缀,但我看不到如何将attr初始化为所需的值。
答案 0 :(得分:0)
我现在通过将方法更改为
来解决此问题private bool ContainsEntity(FileInfo filePath, string entityType, int id, string field, string value)
{
try{
var doc = XDocument.Load(filePath.FullName);
var entities = doc.Descendants(entityType);
XNamespace ns = "http://schemas.sage.com/sdata/2008/1";
XName name = ns + "uuid";
var specificEntities = entities.Where(y => y.Attribute(name).Value.Equals(id));
return specificEntities.Any(ent =>
ent.Elements(field).Any(f => f.Value.Equals(value, StringComparison.OrdinalIgnoreCase)));
}catch{return false;}
}
似乎创建一个显式XName以便在哪里使用。
答案 1 :(得分:0)
答案:
var specificEntities = entities
.Where(y => y.Attributes(nsSys + "uuid").Any(a=>a.Value.Equals(id.ToString())));
或:
var specificEntities = entities
.Where(y => y.Attributes().Any(a => a.Name==(nsSys + "uuid") && a.Value.Equals(id.ToString())));
为什么:
var attr = new XAttribute(ns + "uuid", id);
的属性,并且期望它等于xml文档中的某个属性。新属性不属于文档,因此命名空间的别名是随机的(当然不是“sdata”)Attributes().Contains(attr)
(也因为它比较了对象的引用而不是对象本身)id
是一个int
,因此您应该将其转换为字符串,然后再将其与某个属性(即字符串)的值进行比较。否则Equals()
方法将再次比较对象,并且“1”=! 1 entities.Where(y => y.Attribute(name).Value.Equals(id.ToString()))
在这里很危险。如果您正在寻找名为"depotStore"
的元素,并且那里没有名为"sdata:uuid"
的属性,该怎么办? (这会引起一种误解)。您应该检查null或使用Attributes().Any()