我有以下XML
<itemList>
<Item>
<shipAddress></shipAddress>
<shipMethod></shipMethod>
<rate>50.00</rate>
<custom>
<custcol_1>55</custcol_1>
<custcol_2>60</custcol_2>
</custom>
<special>
<special1>A</special1>
</special>
</Item>
<Item>
<shipAddress></shipAddress>
<rate>50.00</rate>
<custom>
<custcol_1>7889</custcol_1>
<custcol_2>754</custcol_2>
</custom>
</Item>
</itemList>
我要做的是收集<custom>
或<special>
所有节点的列表,因为我想删除它们。
我尝试用以下方法做到这一点,但它没有得到任何节点:
nodesToRemove = xeConsolItm.Elements()
.Where(itm =>
(
itm.Element("custom") != null &&
itm.Element("special") != null &&
itm.Element("other") != null
))
.ToList();
foreach (var xElement in nodesToRemove)
{
nodesToRemove.Remove();
}
我也尝试使用||
,但这也不起作用。在这两种情况下,nodesToRemove
最终都为空。
我想知道一种方法。 我已经能够一次删除每个,但是当我尝试将3合并在一起时,我没有运气。是一次只做一次的最好方法吗?
答案 0 :(得分:2)
您应该使用Descendants()
代替Elements()
来获取任何深度的元素。
此外,您应该使用Name
属性来获取元素的名称。
var nodesToRemove = xeConsolItm.Descendants()
.Where(itm =>
itm.Name == "custom" || itm.Name == "special" || itm.Name == "other")
.ToList();
此外,您还需要按照评论中的说明修复循环。
foreach (var xElement in nodesToRemove)
{
xElement.Remove();
}
@CharlesMager建议的更简单的版本是:
xeConsolItm.Descendants()
.Where(itm =>
itm.Name == "custom" || itm.Name == "special" || itm.Name == "other").Remove();
答案 1 :(得分:0)
@ YacoubMassad的回答是正确的,会给你预期的结果。根据您现有的语法,这是一种不同的(当然不是那么干净)获得结果的方法:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.elements = [
{id: 1, name: 'bonjour'},
{id: 2, name: 'bonsoir'}
];
$scope.text = 'Hello world';
});
app.directive("frameelement", ['$interpolate', function($interpolate) {
return {
restrict: 'EA',
scope: {
thiselem: '='
},
template: '<div ng-bind="getTemplate(thiselem)"></div>',
link: function(scope, element, attrs) {
scope.getTemplate = function(thiselem) {
return $interpolate('<h1>{{thiselem.id}} : {{thiselem.name}} tt</h1>')(scope);
}
}
};
}]);
您当前的代码存在一些问题,即:
var nodesToRemove = xeConsolItm.Elements().Nodes()
.Where(itm =>
itm.ToString().Contains("custom") ||
itm.ToString().Contains("special") ||
itm.ToString().Contains("other")).ToList();
foreach (var xElement in nodesToRemove)
{
xElement.Remove();
}
,而不是Elements
Nodes
Node
"custom" && "special" && "other"
代替nodesToRemove.Remove()
您仍然可以从xElement.Remove();
选择Elements
,但结果会为您提供整个xeConsolItm
,而不仅仅是<Item></Item> Element
。
答案 2 :(得分:0)
我建议创建一个类,然后反序列化/序列化。
通过课程,您可以完全控制并且更容易工作。
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace YourNameSpace
{
[XmlRoot(ElementName="Item")]
public class Item
{
[XmlElement(ElementName="shipAddress")]
public string ShipAddress { get; set; }
[XmlElement(ElementName="shipMethod")]
public string ShipMethod { get; set; }
[XmlElement(ElementName="rate")]
public string Rate { get; set; }
[XmlElement(ElementName="custom")]
public Dictionary<string,int> Custom { get; set; }
[XmlElement(ElementName="special")]
public Dictionary<string,int>Special { get; set; }
}
[XmlRoot(ElementName="itemList")]
public class ItemList
{
[XmlElement(ElementName="Item")]
public List<Item> Item { get; set; }
}
}
当属性具有不同的名称时,我使用Dictionary,然后您可以使用LINQ来访问它们。
获取字典的价值:
var valueOfFirstSpecialElement = Special.FirstOrDefault().Value;
使用XmlSerializer序列化/反序列化:
https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx
在您的情况下,如果您不想要自定义和特殊功能,只需从课程中删除属性,并在反序列化后不再使用它们。