我有一个非常有趣的LINQ问题。我有一个文档,我试图过滤结果,但要过滤,我匹配来自XML的一个元素的REGEX结果。
我有以下工作,使用LINQ to XML来获取我正在寻找的个人数据。
Dim oDocument As XDocument
oDocument = XDocument.Load("test.xml")
Dim results = (From x In oDocument.Descendants.Elements("ROW") _
Select New With {.ApplicationName = GetApplicationName(x.Element("Message")), _
.EventId = x.Element("EventId")}).Distinct
然而,.Distinct没有做我想要的,它仍然显示“ApplicationName”和“EventId”的所有组合。
我最终需要的是一个不同的结果列表,一个带有应用程序名称的新对象,以及来自XML的事件ID。
“GetAPplicationName”是一个解析正在寻找正则表达式匹配的值的函数。
任何指针?
示例XML
<ROOT>
<ROW>
<EventId>1</EventId>
<CreatedTimestamp>2009-10-28</CreatedTimestamp>
<Message>There is a bunch
of
garbled
inforamtion here and I'm trying to parse out a value
Virtual Path: /MyPath then it continues on with more junk after the
message, including extra stuff
</Message>
<!--Other elements removed for brevity -->
</ROW>
<ROW>
<EventId>1</EventId>
<CreatedTimestamp>2009-10-28</CreatedTimestamp>
<Message>
There is a bunch
of
garbled
inforamtion here and I'm trying to parse out a value
Virtual Path: /MyPath then it continues on with more junk after the
message, including extra stuff
</Message>
<!--Other elements removed for brevity -->
</ROW>
</ROOT>
从这里我想要distinct / MyPath和EventId(在这种情况下,1条带/ MyPath和1。
我的GetApplicationNameMethod,此示例将返回/ MyPath
答案 0 :(得分:2)
艾哈迈德的回答是正确的,我赞同它。但是,我只想指出用于LINQ to XML查询的替代VB.NET特定语法。
Dim results = From x In doc...<ROW> _
Select New EventInfo With {.ApplicationName = GetApplicationName(x.<Message>.Value, _
.EventId = x.<EventId>.Value}
这会返回相同的结果,但如果您导入xmlns,那么您将以这种方式获取元素名称的IntelliSense。
这是一篇描述如何在VB.NET中获取XML IntelliSense的文章:
答案 1 :(得分:1)
Distinct不知道如何比较您的商品,因此它会返回所有未过滤的商品。您应该使用Distinct overload that implements IEqualityComparer。这将允许您比较ApplicationName和EventId属性以确定相等性。但是,这样做意味着拥有真正的类,而不是匿名类型。该文档演示了如何以易于理解的方式实现此目的。
编辑:我能够将您的示例与IEqualityComparer和EventInfo类一起使用。我添加了自己的GetApplicationName实现来测试。
Dim results = (From x In doc.Descendants.Elements("ROW") _
Select New EventInfo With {.ApplicationName = GetApplicationName(x.Element("Message")), _
.EventId = x.Element("EventId")})
Console.WriteLine("Total: {0}", results.Count)
Console.WriteLine("Distinct Total: {0}", results.Distinct.Count)
Console.WriteLine("Distinct (w/comparer) Total: {0}", results.Distinct(New EventInfoComparer()).Count)
输出:
Total: 2
Distinct Total: 2
Distinct (w/comparer) Total: 1
其余代码:
' EventInfo class and comparer
Private Function GetApplicationName(ByVal element As XElement)
Return Regex.Match(element.Value, "Virtual\sPath:\s/(\w+)").Groups(1).Value
End Function
Public Class EventInfo
Private _applicationName As String
Public Property ApplicationName() As String
Get
Return _applicationName
End Get
Set(ByVal value As String)
_applicationName = value
End Set
End Property
Private _eventId As Integer
Public Property EventId() As Integer
Get
Return _eventId
End Get
Set(ByVal value As Integer)
_eventId = value
End Set
End Property
End Class
Public Class EventInfoComparer
Implements IEqualityComparer(Of EventInfo)
Public Function Equals1(ByVal x As EventInfo, ByVal y As EventInfo) As Boolean _
Implements IEqualityComparer(Of EventInfo).Equals
' Check whether the compared objects reference the same data.
If x Is y Then Return True
' Check whether any of the compared objects is null.
If x Is Nothing OrElse y Is Nothing Then Return False
' Check whether the EventInfos' properties are equal.
Return (x.ApplicationName = y.ApplicationName) AndAlso (x.EventId = y.EventId)
End Function
Public Function GetHashCode1(ByVal eventInfo As EventInfo) As Integer _
Implements IEqualityComparer(Of EventInfo).GetHashCode
' Check whether the object is null.
If eventInfo Is Nothing Then Return 0
' Get the hash code for the ApplicationName field if it is not null.
Dim hashEventInfoAppName = _
If(eventInfo.ApplicationName Is Nothing, 0, eventInfo.ApplicationName.GetHashCode())
' Get the hash code for the EventId field.
Dim hashEventInfoId = eventInfo.EventId.GetHashCode()
' Calculate the hash code for the EventInfo.
Return hashEventInfoAppName Xor hashEventInfoId
End Function
End Class
答案 2 :(得分:1)
我之前从未注意到这一点,但似乎VB的匿名类型不会覆盖Equals()
和GetHashcode()
。因此,Distinct()
正在检查引用相等性。最简单的解决方法是构建自己的实现IEquatable<T>
的类。