c# - 根据属性查找 XML 元素
问题描述
假设我有这个 XML
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" mergefield="blah">
<filter blah="rrr"></filter>
<filter blah="qqq"></filter>
<filter blah="www"></filter>
</hibernate-mapping>
如果targetElement
在sourceElement
namespace Test
{
class Program
{
static void Main(string[] args)
{
var path = (@"PATHFORXML");
XElement target = XElement.Load(path);
XElement source = XElement.Load(path);
foreach (var sourceElement in source.Elements())
{
XElement targetElement = target.Elements().SingleOrDefault(
t =>
String.Equals(
(string)t.Attribute(GetMergeAttr(target)),
(string)sourceElement.Attribute(GetMergeAttr(source)),
StringComparison.InvariantCultureIgnoreCase)
);
}
Console.ReadLine();
}
private static string GetMergeAttr(XElement element)
{
return (string)element.Attribute("mergefield");
}
}
}
问题
现在我有一种情况,mergefield
可以是"blah"
or "blahblah"
。所以我希望上面的代码对这个 XML 以同样的方式工作:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" mergefield="blah,blahblah">
<filter blah="rrr"></filter>
<filter blahblah="qqq"></filter>
<filter blahblah="www"></filter>
</hibernate-mapping>
Aka,任何一个都mergefields
应该工作
我的尝试就是这些。GetMergeAttr
应该变成这样:
private static string[] GetMergeAttr(XElement element)
{
var f = ((string)element.Attribute("mergefield")).Split(',');
return f;
}
我无法完成查询部分
XElement targetElement = target.Elements().SingleOrDefault(
t =>
String.Equals(
(string)t.Attribute(GetMergeAttr(target).SingleOrDefault(u=> ?????????)),
(string)sourceElement.Attribute(GetMergeAttr(source).SingleOrDefault(u => ?????????))
)
);
这可行,但是如果我有 3 个以上的合并字段值怎么办(我需要更新此查询以接受任意数量的合并字段,而不仅仅是 2 个):
XElement targetElement = target.Elements().SingleOrDefault(
t =>
String.Equals(
(string)t.Attribute(GetMergeAttr(target).Last())?? (string)t.Attribute(GetMergeAttr(target).First()),
(string)sourceElement.Attribute(GetMergeAttr(source).Last()) ?? (string)sourceElement.Attribute(GetMergeAttr(source).First())
)
);
解决方案
根据评论更新。
我假设以下是您需要的
XElement target = XElement.Parse(txml);
XElement source = XElement.Parse(sxml);
var targetMergeAttrs = GetMergeAttr(target);
var sourceMergeAttrs = GetMergeAttr(source);
foreach (var sourceElement in source.Elements())
{
foreach(var mergeField in sourceMergeAttrs)
{
if(sourceElement.Attributes().Any(x=>x.Name.LocalName.Equals(mergeField)) &&
target.Elements()
.Any(x=>x.Attributes()
.Where(c=>c.Name.LocalName == mergeField
&& targetMergeAttrs.Contains(mergeField)
&& c.Value == (string)sourceElement.Attribute(mergeField)).Any()
))
{
XElement targetElement = target.Elements()
.FirstOrDefault(x=>x.Attributes()
.Where(c=>c.Name.LocalName == mergeField
&& targetMergeAttrs.Contains(mergeField)
&& c.Value == (string)sourceElement.Attribute(mergeField)).Any()
);
// Do work with targetElement
break;
}
}
}
推荐阅读
- node.js - 如何在节点 js 中读取大型 json 文件?
- python - 我可以在 conv3d 层之后使用 BatchNornalization 层吗?
- batch-file - 使用批处理文件打开vscode时,cmd打开并且不关闭
- html - 我们应该使用
- python - 计算任意数的最大素因数
- c# - ForeignKey 注释似乎不起作用
- algorithm - 如何修改二维矩阵以便满足两个维度的预定义总和?
- javascript - 如何在 Javascript 对象中定义方法?
- python - 将字符串转换为不带日期的 pandas 时间戳
- computer-vision - 是否有任何现有模型可以帮助从游戏视频中提取投篮图表数据?