【问题标题】:search string in value and get attribute value in LINQ to XML in VB.NET在值中搜索字符串并在 VB.NET 中的 LINQ to XML 中获取属性值
【发布时间】: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

【问题讨论】:

    标签: xml vb.net linq-to-xml


    【解决方案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 })
        

      演示小提琴herehere

      【讨论】:

      • 谢谢。它工作正常。但第二个答案更有原则。
      猜你喜欢
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      • 2013-02-22
      • 1970-01-01
      • 2013-01-10
      相关资源
      最近更新 更多