在值中搜索字符串并在 VB.NET 中的 LINQ to XML 中获取属性值

Posted

技术标签:

【中文标题】在值中搜索字符串并在 VB.NET 中的 LINQ to XML 中获取属性值【英文标题】:search string in value and get attribute value in LINQ to XML in VB.NET 【发布时间】:2021-12-28 06:59:26 【问题描述】:

我有一个 XML 文件,我想使用 Contains 命令搜索“val”的值并获取它的“index”属性以及“catalog name”属性。

<list>
    <catalog index="1" name="n1">
        <val index="1">sample text 1</val>
        <val index="2">sample text 2</val>
        <val index="3">sample text 3</val>
    </catalog>
    <catalog index="2" name="n2">
        <val index="1">sample text 0</val>
        <val index="2">sample text 2</val>
        <val index="3">sample text 3</val>
        <val index="4">sample text 1</val>
        <val index="5">sample text 5</val>
        <val index="6">sample text 6</val>
    </catalog>
    <catalog index="3" name="n3">
        <val index="1">sample text 8</val>
        <val index="2">sample text 9</val>
        <val index="3">sample text 10</val>
    </catalog>
</list>

我用过

Dim xml_Doc = XDocument.Load(myPath & "list.Xml")

Dim search_result As IEnumerable(Of XElement)
search_result =
        (From c In xml_Doc.Descendants("catalog")
         Where c.Elements("val").Value.Contains("sample text 1")
         Select c.Elements("val").Attributes("index").ToString & c.Attribute("name").Value)

我该怎么做?

输出应该如下:

index:1 , name: n1
index:4 , name: n2

【问题讨论】:

【参考方案1】:

免责声明:我喜欢 XmlSerialization。强类型和可重用的对象。我会首先通过创建一些类来将文件序列化为

来解决这个问题
Imports System.IO
Imports System.Xml.Serialization
<XmlRoot("list")>
Public Class List
    <XmlElement("catalog")>
    Public Property Catalogs As List(Of Catalog)
End Class

Public Class Catalog
    <XmlElement("val")>
    Public Property Vals As List(Of Val)
    <XmlAttribute("index")>
    Public Property Index As Integer
    <XmlAttribute("name")>
    Public Property Name As String
End Class

Public Class Val
    <XmlAttribute("index")>
    Public Property Index As Integer
    <XmlText>
    Public Property Text As String
End Class

然后反序列化文件

Dim list As List
Dim serializer As New XmlSerializer(GetType(List))
Using sr As New StreamReader("list.xml")
    list = CType(serializer.Deserialize(sr), List)
End Using

现在您的 xml 位于 .NET 类中,您可以使用 LINQ 来获取您想要的内容

Dim searchString = "sample text 1"
Dim catalogs As New List(Of Catalog)()
For Each catalog In list.Catalogs
    Dim vals = catalog.Vals.Where(Function(val) val.Text = searchString)
    For Each val In vals
        catalogs.Add(New Catalog() With .Vals = val.ToList(), .Name = catalog.Name, .Index = catalog.Index)
    Next
Next
Dim search_results = catalogs.SelectMany(Function(c) c.Vals.Select(Function(v) $"index:v.Index, name: c.Name"))
For Each search_result In search_results
    Console.WriteLine(search_result)
Next

输出:

索引:1,名称:n1 索引:4,名称:n2

它有点笨拙,因为您希望 m 个项目来自 n 到 m 的关系(n 个目录和 m 个 val),因此我们使用 SelectMany 将目录投影到 val 的数量中。但是list 对象拥有您可以使用的所有数据。

如另一个答案中所述,您正在搜索包含“示例文本 1”但返回“示例文本 10”的字符串,并且根据您想要的输出,您应该搜索完全匹配。 em>

【讨论】:

【参考方案2】:

最简单的方法是在c.Elements("val") 元素上嵌套From 查询,如下所示:

Dim sampleText = "sample text 1"
Dim search_result = 
    (From c In xml_Doc.Descendants("catalog")
    From v in c.Elements("val")
    Where v.Value.Contains(sampleText)
    Select New With .index = v.Attribute("index").Value, .name = c.Attribute("name").Value )
    
For Each s In search_result
    Console.WriteLine("index:0 , name:1", s.index, s.name)
Next

产生:

index:1 , name:n1
index:4 , name:n2
index:3 , name:n3

注意事项:

这样做可以让您轻松过滤内部元素v 的值,然后从v 和外部元素c 中选择属性。

index:3 , name:n3 包含在结果中,因为此元素的文本 sample text 10 包含搜索字符串 sample text 1。如果您不希望包含此元素,请将您的 Where 子句更改为使用相等:

 Dim search_result = 
     (From c In xml_Doc.Descendants("catalog")
     From v in c.Elements("val")
     Where v.Value = sampleText
     Select New With .index = v.Attribute("index").Value, .name = c.Attribute("name").Value )

演示小提琴here 和here。

【讨论】:

谢谢。它工作正常。但第二个答案更有原则。

以上是关于在值中搜索字符串并在 VB.NET 中的 LINQ to XML 中获取属性值的主要内容,如果未能解决你的问题,请参考以下文章

在值中使用与号 (&) 时 List.js 不起作用

LINQ .Startswith 或 .Contains VB.NET4 中的问题

vb.net 中 LINQ 的新手问题

使用 Linq 在值之间添加逗号

jQuery获取特定的选项标签文本并将动态变量放置在值中

在 VB.NET 中使用带有匿名方法的 LINQ 的 ForEach