在自我之前获取元素
本文关键字:获取 元素 自我 | 更新日期: 2023-09-27 18:35:42
如果当前的"Name"元素为空或空,则应采用前一个元素的"Name"值。第一个元素名称永远不会为 null 或空。
我需要获取前面的元素"名称"值,其中当前"名称"元素值为空或空:
List<ScripTbl> ScripData = ScrpHldNode.Descendants(ns + "Scrp").Select(x => new ScripTbl
{
ID = sID,
//need help with the line below....
ScripShare = (!string.IsNullOrEmpty((String)x.Element(ns + "Name")) ? (String)x.Element(ns + "Name") : (x.ElementsBeforeSelf().Count() > 0 ? (String)x.ElementsBeforeSelf().Last().Element(ns + "Name") : "")),
ScripOpenBalanceDue = (String)x.Element(ns + "OpBal"),
ScripClosingBalance = (String)x.Element(ns + "ClBal"),
ScripTransaction = (String)x.Element(ns + "Tran"),
ScripMovement = (String)x.Element(ns + "Move"),
ScripFooter = sScripFooter,
Seq = x.ElementsBeforeSelf().Count() + 1,
ScripSectorCode = (String)x.Element(ns + "SecCde"),
ScripClosingPrice = (String)x.Element(ns + "ClPrce"),
SplitIndicator = (!string.IsNullOrEmpty((String)x.Element(ns + "Name")) ? (x.ElementsBeforeSelf().Count() > 0 && (String)x.Element(ns + "Name") == (String)x.ElementsBeforeSelf().Last().Element(ns + "Name") ? "1" : "0") : "0")
}).ToList();
和 XML:
<ScrpHld xmlns="http://www.website.co.za/namespace">
<Scrp>
<Name>Company Name Number 1</Name>
<SecCde>1366J</SecCde>
<Tran>SOLD</Tran>
<OpBal>0</OpBal>
<Move>-2000</Move>
</Scrp>
<Scrp>
<Tran>ELECTRONIC SETTLEMENT</Tran>
<Move>2000</Move>
<ClPrce>25045.00</ClPrce>
<ClBal>0</ClBal>
</Scrp>
<Scrp>
<Name>Company Name Number 2</Name>
<SecCde>1313J</SecCde>
<Tran>SOLD</Tran>
<OpBal>10000</OpBal>
<Move>-90500</Move>
</Scrp>
<Scrp>
<Tran>ELECTRONIC SETTLEMENT</Tran>
<Move>80500</Move>
<ClPrce>3392.00</ClPrce>
<ClBal>0</ClBal>
</Scrp>
</ScrpHld>
使用 PreviousNode
而不是 ElementsBeforeSelf
,它会更容易。我分成多行只是为了增加答案的可读性。
该行应如下所示
ScripShare = (x.Element(ns + "Name") != null
? (string)x.Element(ns + "Name")
: (x.PreviousNode != null
? ((XElement)x.PreviousNode).Element(ns + "Name").Value
: string.Empty)),
如果您的xml将在元素中包含注释或任何其他文本,则应检查上一个节点是否为XElement
类型,而不是coment(XComent
)或文本(XText
),那么在这种情况下,使用ElementsBeforeSelf
ScripShare = (x.Element(ns + "Name") != null
? (string)x.Element(ns + "Name")
: (x.NodesBeforeSelf().Last(e => e.NodeType == XmlNodeType.Element) != null
? ((XElement)x.NodesBeforeSelf().Last(e => e.NodeType == XmlNodeType.Element)).Element(ns + "Name").Value
: string.Empty)),
试试这个:
private static string ns = "{http://www.website.co.za/namespace}";
private static string getName(XElement x) {
if (x == null)
throw new InvalidOperationException("First elements has no Name");
var val = (string) x.Element(ns + "Name");
return val ?? getName((XElement)x.PreviousNode);
}
static void Main(string[] args)
{
string xml = @"<ScrpHld xmlns=""http://www.website.co.za/namespace"">
<Scrp>
<Name>Company Name Number 1</Name>
<SecCde>1366J</SecCde>
<Tran>SOLD</Tran>
<OpBal>0</OpBal>
<Move>-2000</Move>
</Scrp>
<Scrp>
<Tran>ELECTRONIC SETTLEMENT</Tran>
<Move>2000</Move>
<ClPrce>25045.00</ClPrce>
<ClBal>0</ClBal>
</Scrp>
<Scrp>
<Name>Company Name Number 2</Name>
<SecCde>1313J</SecCde>
<Tran>SOLD</Tran>
<OpBal>10000</OpBal>
<Move>-90500</Move>
</Scrp>
<Scrp>
<Tran>ELECTRONIC SETTLEMENT</Tran>
<Move>80500</Move>
<ClPrce>3392.00</ClPrce>
<ClBal>0</ClBal>
</Scrp>
</ScrpHld>";
XDocument doc = XDocument.Parse(xml);
var result = doc.Descendants(ns + "Scrp").Select(x => new
{
Name = getName(x)
});
foreach (var item in result)
{
Console.WriteLine(item.Name);
}
此方法使用递归方法,因此即使两个连续的元素没有名称,它们也将具有前一个元素的名称。
您可以声明用于捕获选择方法范围之外的当前名称的变量:
string name = "";
scripData = ScrpHldNode.Descendants(ns + "Scrp")
.Select(scrp => {
var currentName = (string)scrp.Element(ns + "Name");
if (!String.IsNullOrEmpty(currentName))
name = currentName;
return new ScripTbl {
ScripShare = name
// ...
};
});
没有递归,没有遍历先前元素的 xml 树。
如果只需要检查缺少的名称元素,则可以将代码缩短为
string name = "";
var scripData = from scrp in ScrpHldNode.Descendants(ns + "Scrp")
let currentName = (string)scrp.Element(ns + "Name") ?? name
select new ScripTbl {
ScripShare = (name = currentName)
// ...
};
它更短(由于 null 合并运算符的使用和 ScripShare 分配期间棘手的名称分配),但我会使用更长、更明显的代码。