有人可以协助解决此.NET Linq查询问题。它应该工作,但是不行,并且找不到元素。该查询的结果应为106492,但只返回null。太棒了!
这是.Net小提琴代码:
using System;
using System.Xml.Linq;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
String rxml = @"<TestMessage>
<TestIdentification>
<TestID>106491</TestID>
<TestType>TESTID1</TestType>
</TestIdentification>
<TestIdentification>
<TestID>106492</TestID>
<TestType>TESTID2</TestType>
</TestIdentification>
<TestIdentification>
<TestID>106493</TestID>
<TestType>TESTID3</TestType>
</TestIdentification>
<TestIdentification>
<TestID>106494</TestID>
<TestType>TESTID4</TestType>
</TestIdentification>
</TestMessage>
";
XElement xml = XElement.Parse(rxml);
// Read all response fields responseLog class
var testObj = (from el in xml.DescendantsAndSelf()
select new TestClassObj
{
TestID = el.Elements("TestIdentification").Elements("TestType").
Where( c => c.Value == "TESTID2" ).Elements("TestID").
Where( c => !string.IsNullOrWhiteSpace(c.Value)).FirstOrDefault().Value,
}).FirstOrDefault();
if( testObj != null )
Console.WriteLine(testObj.TestID);
}
}
public class TestClassObj
{
public String TestID{ get; set; }
public String TestText{ get; set; }
}
答案 0 :(得分:4)
首先,我删除了“外部”查询部分:
(from el in xml.DescendantsAndSelf()
select new TestClassObj { ... }).FirstOrDefault()
鉴于您选择的TestIdentification
元素仅在根元素的正下方,因此该查询是没有意义的-它只会为根元素找到任何内容。
接下来,我已经删除了TestClassObj
的用法-您仅将其用作包装字符串的方式,因此您最好直接使用该字符串。
接下来,更改查询的焦点:您不是要查找TestType
元素,而是要找到一个具有正确的TestIdentification
子元素的TestType
元素。然后,您可以找到同一TestID
元素的TestIdentification
元素。
接下来,我使用了从XElement
到string
的转换,而不是使用Value
属性。在对null元素进行调用时,强制转换只会返回null,而不是抛出NullReferenceException
。当您只想忽略没有预期子元素/属性的元素时,这是LINQ to XML中非常有用的方法。
剩下的是:
var testId = xml.Elements("TestIdentification")
.Where(x => (string) x.Element("TestType") == "TESTID2")
.Select(x => (string) x.Element("TestID"))
.FirstOrDefault();
Console.WriteLine(testId);
这将按预期打印出106492。
另一种选择是找到合适的TestType
元素,然后导航到其父元素并找到其TestID
子元素:
var testId = xml.Elements("TestIdentification")
.Elements("TestType")
.Where(x => (string) x == "TESTID2")
.Select(x => (string) x.Parent.Element("TestID"))
.FirstOrDefault();
Console.WriteLine(testId);
效果也一样;使用您认为最容易使用的任何形式。
答案 1 :(得分:1)
您可以尝试让System.Xml.Linq为您完成更多工作。这样的事情可能会更简单。
class DayCollectionViewCell: UICollectionViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func clearArrow(){
self.layer.sublayers = nil
}
func drawArrow(){
let start_x = self.bounds.minX
let start_y = self.bounds.minY
let top_width = self.bounds.width
let tick_height = self.bounds.height
let tip_height = CGFloat(10)
let tip_flare = CGFloat(6)
let arrowLayer = CAShapeLayer()
let path = UIBezierPath()
path.move(to: CGPoint(x: start_x, y: start_y + tick_height))
path.addLine(to: CGPoint(x: start_x + top_width,y: start_y + tick_height))
path.addLine(to: CGPoint(x: start_x + top_width + tip_flare,y: start_y+tick_height+tip_height))
path.addLine(to: CGPoint(x: start_x - tip_flare,y: start_y + tick_height + tip_height))
path.close()
arrowLayer.path = path.cgPath
arrowLayer.fillColor = UIColor(red:0.99, green:0.13, blue:0.25, alpha:1.0).cgColor
self.layer.addSublayer(arrowLayer)
}
override var isSelected: Bool{
didSet{
if self.isSelected
{
self.drawArrow()
}
else
{
self.clearArrow()
}
}
}
}
答案 2 :(得分:1)
您想在Element
的子级上使用Elements
而不是TestIdentification
并合并过滤器。
var testObj = (from el in xml.DescendantsAndSelf().Elements("TestIdentification")
where el.Element("TestType").Value == "TESTID2" && !string.IsNullOrWhiteSpace(el.Element("TestID")?.Value)
select new TestClassObj { TestID = el.Element("TestID").Value })
.FirstOrDefault();
Console.WriteLine(testObj.TestID); // 106492