C# LINQ-XML选择节点通用
我试图剥离XML,只保留我需要的节点 输入XML是C# LINQ-XML选择节点通用,c#,xml,linq,xml-parsing,linq-to-xml,C#,Xml,Linq,Xml Parsing,Linq To Xml,我试图剥离XML,只保留我需要的节点 输入XML是 <Employees> <Employee> <EmpId>1</EmpId> <Name>Sam</Name> <Sex>Male</Sex> <Address> <Country>USA</Country> <Zip>95220</
<Employees>
<Employee>
<EmpId>1</EmpId>
<Name>Sam</Name>
<Sex>Male</Sex>
<Address>
<Country>USA</Country>
<Zip>95220</Zip>
</Address>
<Address2>
<Country>UK</Country>
<Zip>E157JQ</Zip>
</Address2>
</Employee>
<Employee>
<EmpId>2</EmpId>
<Name>Lucy</Name>
<Sex>Female</Sex>
<Address>
<Country>USA</Country>
<Zip>95220</Zip>
</Address>
<Address2>
<Country>UK</Country>
<Zip>E184JQ</Zip>
</Address2>
</Employee>
</Employees>
我从上面得到的输出是
<Employees>
<Employee>
<EmpId>1</EmpId>
<Sex>Male</Sex>
<Address>
<Country>USA</Country>
<Zip>95220</Zip>
</Address>
<Address2>
<Country>UK</Country>
<Zip>E157JQ</Zip>
</Address2>
</Employee>
<Employee>
<EmpId>2</EmpId>
<Sex>Female</Sex>
<Address>
<Country>USA</Country>
<Zip>95220</Zip>
</Address>
<Address2>
<Country>UK</Country>
<Zip>E184JQ</Zip>
</Address2>
</Employee>
</Employees>
1.
男性
美国
95220
英国
E157JQ
2.
女性
美国
95220
英国
E184JQ
我需要的输出是
<Employees>
<Employee>
<EmpId>1</EmpId>
<Sex>Male</Sex>
<Address>
<Zip>95220</Zip>
</Address>
<Address2>
<Country>UK</Country>
</Address2>
</Employee>
<Employee>
<EmpId>2</EmpId>
<Sex>Female</Sex>
<Address>
<Zip>95220</Zip>
</Address>
<Address2>
<Country>UK</Country>
</Address2>
</Employee>
</Employees>
1.
男性
95220
英国
2.
女性
95220
英国
如何查询Address\Zip和Address2\Country我需要这是通用的(因此可以更改字符串保留),所以我无法硬编码节点名称
谢谢好吧,这取决于你有多希望这是通用的。 这是一种保留当前代码结构的有点粗俗的方法
string keep = @"EmpId,Sex,Address,Address\Zip,Address2,Address2\Country";
string desStr = "Employee";
string[] strArr = keep.Split(',');
var nodesToDelete = xDoc.Root.Descendants(desStr)
.SelectMany(el => el.Descendants()
.Where(a =>
{
if (a.Parent.Name == desStr)
{
return !strArr.Contains(a.Name.ToString());
}
else
{
return !strArr.Contains(a.Parent.Name + @"\" + a.Name);
}
}));
foreach (var node in nodesToDelete.ToList())
node.Remove();
正确的方法是保留所有要保留的节点的完整路径。我的方法:
string keep = "Employees,Employee,EmpId,Sex,Address2,Address,Address.Zip,Address2.Country"; // I can change this format
string[] strArr = keep.Split(',');
foreach (var node in xDoc.Descendants().ToArray())
{
var path = Path(node);
if (!strArr.Any(path.EndsWith))
{
node.Remove();
}
}
var results = xDoc.ToString();
}
private static string Path(XElement x)
{
if (x.Parent != null)
{
return Path(x.Parent) + "." + x.Name;
}
return x.Name.ToString();
}
你到底想干什么?您想让XML看起来像地址节点下总是只有Zip,地址2下总是只有国家/地区吗?我试图让它成为输入驱动的,所以如果字符串keep=“EmpId,Sex,Address,Zip,Address2,Country”\ \我可以更改此格式,因此如果是Address\Zip,那么我的XML应该有95220如果是Address\Country,那么我的XML应该是UK您需要输入保持字符串格式吗?因为您尝试执行的操作需要一个类似于树的输入定义,所以解析这样的字符串将很麻烦。不必是字符串格式。它将作为字符串传递,但我可以将其转换为任何格式/对象。问题是您是通过UI从最终用户还是从某些配置接收输入。在配置的情况下,最好使用最终XML格式的XSD;对于用户输入,您要么提供一个方便的UI,要么发明另一种格式,允许您指定节点的层次结构。
string keep = "Employees,Employee,EmpId,Sex,Address2,Address,Address.Zip,Address2.Country"; // I can change this format
string[] strArr = keep.Split(',');
foreach (var node in xDoc.Descendants().ToArray())
{
var path = Path(node);
if (!strArr.Any(path.EndsWith))
{
node.Remove();
}
}
var results = xDoc.ToString();
}
private static string Path(XElement x)
{
if (x.Parent != null)
{
return Path(x.Parent) + "." + x.Name;
}
return x.Name.ToString();
}