在VB.Net中存储XML上的属性

时间:2016-03-30 15:21:07

标签: xml vb.net

我使用这种通用格式创建了一个XML,但是存储属性存在困难:

<?xml version="1.0">
-<Report>
    -<Class Name="ClassA">
        <Property Name="Property1" dType="Boolean">False</Property>
    </Class>
    -<Class Name="ClassB">
        -<Property Name="Property2" dType="SortedList`2" Value="String" Key="Int16">
            <SrtLstItm Key="1">94</SrtLstItm>
        </Property>
        <Property Name="Property3" dType="Int32">1</Property>
        -<Property Name="Property4" dType="List`1" Type="Product">
            <LstItm Name="Property4">LstItm1</LstItm>
            <LstItm Name="Property4">LstItm2</LstItm>
        </Property>
    </Class>
    -<Class Name="ClassC">
        <Property Name="Property5" dType="String">50.5</Property>
    </Class>
</Report>

我感兴趣的是使用XMLTextReader来存储类名,因为它正在读取属性,它仍然具有类信息。我目前正在使用NodeType的Select Case:

Dim xrdr = New System.Xml.XmlTextReader(fileName)
Do While (xrdr.Read())
  Select Case xrdr.NodeType
    Case XmlNodeType.Element 'Display beginning of element.'
      Select Case xrdr.Name
        Case xrdr.Name = "Class"
          cls = xrdr.GetAttribute("Name")
        Case xrdr.Name = "Property"
          propertyName = xrdr.GetAttribute("Name")
        Case xrdr.Name = "SrtListItm"
          srtLstKey = xrdr.GetAttribute("Key")
      End Select
      If xrdr.HasAttributes Then 'If attributes exist'
        While xrdr.MoveToNextAttribute()
          ''Display attribute name and value.              
        End While
      End If
    Case XmlNodeType.Text 'Display the text in each element.'
      vle = xrdr.ReadString
    Case XmlNodeType.EndElement 'Display end of element.'
  End Select
Loop
xrdr.Close()

我计划使用代码使用XML中给出的更新值更新每个类的公共属性。在此之前我使用了XML,因此每个属性都有一个class属性,代码可以读取和更新所有没有子节点的属性。我重组它以考虑数组类型的属性。任何帮助将不胜感激,谢谢你的时间。

更新:使用发布的解决方案我想出了以下内容。 从上面的代码我能够读取所有非数组属性。现在我正在尝试从子项中导入值。

Dim xrdr = New System.Xml.XmlTextReader(fileName)
Do While (Not xrdr.EOF)
  xrdr.ReadToFollowing("Class")
  If (Not xrdr.EOF) Then
    Dim _class As XElement = XElement.ReadFrom(xrdr)
    Dim cls As String = _class.Attribute("Name")
    For Each _property As XElement In _class.Elements("Property")
      Dim propertyName As String = _property.Attribute("Name")
      fInfo = ps.GetType().GetField("_" & cls,
           System.Reflection.BindingFlags.NonPublic Or
           System.Reflection.BindingFlags.Instance Or
           System.Reflection.BindingFlags.Public Or
           System.Reflection.BindingFlags.IgnoreCase)
      'Use the FieldInfo to retrieve the sub-class the matches the cls variable.'
        obj = fInfo.GetValue(object)'Object created before read'

      'Using reflection, get the PropertyInfo of the Property that matches'
      'the text in the nme variable.'
      pInfo = obj.GetType.GetProperty(propertyName)
      If pInfo Is Nothing Then

      Else
        Dim pInfoType = pInfo.PropertyType.Name

        If pInfoType = "SortedList`2" Then
          For Each _child As XElement In _property.Elements("SrtLstItm")
            Dim childName As String = _child.Attribute("Key")
            pInfo = obj.GetType.GetProperty(childName)
            tmpVal = CTypeDynamic(_child.Value, pInfo.PropertyType)
            pInfo.SetValue(obj, tmpVal, Nothing)
          Next
        ElseIf pInfoType = "List`1" Then
        ElseIf pInfoType = "Product" Then
        Else
          'Convert the value (vle) to the type of the Property to which
          'it will be assigned.  CTypeDynamic must be used so that the
          'type retrieved from pInfo can be used.
          tmpVal = CTypeDynamic(_property.Value, pInfo.PropertyType)
          'Use the PropertyInfo to set the value of the property
          'that matches nme. 
          pInfo.SetValue(obj, tmpVal, Nothing)
        End If

      End If

    Next _property

  End If
Loop

2 个答案:

答案 0 :(得分:2)

这是一种使用Linq

的XmlTextReader更简单的方法
Imports System.Xml
Imports System.Xml.Linq
Module Module1
    Const FILENAME As String = "c:\temp\test.xml"
    Sub Main()
        Dim xrdr = New System.Xml.XmlTextReader(FILENAME)
        Do While (Not xrdr.EOF)
            xrdr.ReadToFollowing("Class")
            If (Not xrdr.EOF) Then
                Dim _class As XElement = XElement.ReadFrom(xrdr)
                Dim results = GetClass(_class)
            End If
        Loop

    End Sub
    Function GetClass(_class As XElement) As Object
        Return _class.DescendantsAndSelf().Select(Function(x) New With {
                 .name = x.Attribute("Name").Value,
                 .properties = x.Elements("Property").Select(Function(y) New With {
                        .name = CType(y.Attribute("Name"), String),
                        .dType = CType(y.Attribute("dType"), String),
                        .value = CType(y.Attribute("Value"), String),
                        .key = CType(y.Attribute("Key"), String),
                        .sortedLstItm = y.Elements("SrtLstItm").Select(Function(z) New With {
                                .key = CType(z.Attribute("Key"), String),
                                .value = Integer.Parse(z.Value)
                        }).ToList(),
                        .lstItms = y.Elements("LstItm").Select(Function(z) New With {
                            .name = CType(z.Attribute("Name"), String),
                            .value = z.Value
                        }).ToList()
                  }).ToList()
        }).FirstOrDefault()
    End Function
End Module

答案 1 :(得分:1)

使用您的示例,我想出了两种方法来处理DOM。第一个使用XmlDocument,第二个使用XmlTextReader。我将两者放入一个将信息输出到TextBox的示例中。我是这样做的,以防您发现使用XmlDocument更容易跟踪您所在的级别。在任何一种情况下,您都需要捕获每个唯一元素(Class,Property,Property children等)的开头并相应地使用。

这是我创建的用于解析文件的单个子目录:

Private Sub ReadXmlData(ByRef fileName As String)

  Dim cls As String = String.Empty
  Dim propertyName As String = String.Empty
  Dim srtLstKey As String = String.Empty
  Dim vle As String = String.Empty
  Dim counter As Integer = 0

  Dim output As StringBuilder = New StringBuilder()

  '
  '-- METHOD 1: XmlDocument --
  '

  'Notice how this one could benefit from recursive calls to a single function due to the nested child nodes.

  Dim xDoc As XmlDocument = New XmlDocument()
  xDoc.Load(fileName)

  Dim node As XmlNode
  Dim child As XmlNode
  Dim child2 As XmlNode
  Dim attr As XmlAttribute
  counter = 1
  For Each node In xDoc.DocumentElement.ChildNodes
     output.AppendLine("#" & counter.ToString() & ": " & node.Name)
     For Each attr In node.Attributes
        output.AppendLine("Attribute [" & attr.Name & "] = " & attr.Value)
     Next
     If node.HasChildNodes Then
        For Each child In node.ChildNodes
           output.AppendLine("-- Child [" & child.Name & "] = " & child.Name)
           If child.InnerText.Length > 0 Then output.AppendLine("---- (Text): " & child.InnerText)
           If child.Attributes IsNot Nothing Then
              For Each attr In child.Attributes
                 output.AppendLine("---- Attribute [" & attr.Name & "] = " & attr.Value)
              Next
           End If
           If child.HasChildNodes Then
              For Each child2 In child.ChildNodes
                 output.AppendLine("------ Child [" & child2.Name & "] = " & child2.Name)
                 If child2.InnerText.Length > 0 Then output.AppendLine("------ (Text): " & child2.InnerText)
                 If child2.Attributes IsNot Nothing Then
                    For Each attr In child2.Attributes
                       output.AppendLine("------ Attribute [" & attr.Name & "] = " & attr.Value)
                    Next
                 End If
              Next
           End If
        Next
     End If
     counter += 1
  Next
  output.Append("=", 30)
  output.AppendLine()

  '
  '-- METHOD 2: XmlTextReader --
  '

  Dim xrdr = New System.Xml.XmlTextReader(fileName)

  counter = 1
  Do While (xrdr.Read())
     If xrdr.NodeType = XmlNodeType.Element Then
        output.Append("-", 20)
        output.Append(" " & counter.ToString() & " ")
        output.Append("-", 20)
        output.AppendLine()
        counter += 1
     End If
     output.AppendLine(xrdr.NodeType.ToString())
     Select Case xrdr.NodeType
        Case XmlNodeType.Element 'Display beginning of element.
           output.AppendLine("NODETYPE -- Name: " & xrdr.Name)
           Select Case xrdr.Name
              Case "Class"
                 cls = xrdr.GetAttribute("Name")
                 output.AppendLine("Class: " & cls)
              Case "Property"
                 propertyName = xrdr.GetAttribute("Name")
                 output.AppendLine("Property: " & propertyName)
              Case "SrtLstItm"
                 srtLstKey = xrdr.GetAttribute("Key")
                 output.AppendLine("SrtLstItm Key: " & srtLstKey)
              Case "LstItm"
                 output.AppendLine("LstItm: Name=" & xrdr.GetAttribute("Name"))
           End Select
           If xrdr.HasAttributes Then 'If attributes exist
              While xrdr.MoveToNextAttribute()
                 output.AppendLine("Attribute [" & xrdr.Name & "] = " & xrdr.Value)
              End While
           End If
        Case XmlNodeType.Text 'Display the text in each element.
           vle = xrdr.ReadString
           output.AppendLine("(Text): " & vle)
        Case XmlNodeType.EndElement 'Display end of element.
           output.Append("-", 10)
           output.Append(" [End Element] ")
           output.Append("-", 10)
           output.AppendLine()
     End Select
  Loop
  xrdr.Close()

  XmlOutput.Text = output.ToString()
End Sub

XmlOutput的输出如下所示。忽略语法突出显示。我无法使用blockquote,因为它将各种字符解析为标记。

#1: Class
Attribute [Name] = ClassA
-- Child [Property] = Property
---- (Text): False
---- Attribute [Name] = Property1
---- Attribute [dType] = Boolean
------ Child [#text] = #text
------ (Text): False
#2: Class
Attribute [Name] = ClassB
-- Child [Property] = Property
---- (Text): 94
---- Attribute [Name] = Property2
---- Attribute [dType] = SortedList`2
---- Attribute [Value] = String
---- Attribute [Key] = Int16
------ Child [SrtLstItm] = SrtLstItm
------ (Text): 94
------ Attribute [Key] = 1
-- Child [Property] = Property
---- (Text): 1
---- Attribute [Name] = Property3
---- Attribute [dType] = Int32
------ Child [#text] = #text
------ (Text): 1
-- Child [Property] = Property
---- (Text): LstItm1LstItm2
---- Attribute [Name] = Property4
---- Attribute [dType] = List`1
---- Attribute [Type] = Product
------ Child [LstItm] = LstItm
------ (Text): LstItm1
------ Attribute [Name] = Property4
------ Child [LstItm] = LstItm
------ (Text): LstItm2
------ Attribute [Name] = Property4
#3: Class
Attribute [Name] = ClassC
-- Child [Property] = Property
---- (Text): 50.5
---- Attribute [Name] = Property5
---- Attribute [dType] = String
------ Child [#text] = #text
------ (Text): 50.5
==============================
XmlDeclaration
Whitespace
-------------------- 1 --------------------
Element
NODETYPE -- Name: Report
Whitespace
-------------------- 2 --------------------
Element
NODETYPE -- Name: Class
Class: ClassA
Attribute [Name] = ClassA
Whitespace
-------------------- 3 --------------------
Element
NODETYPE -- Name: Property
Property: Property1
Attribute [Name] = Property1
Attribute [dType] = Boolean
Text
(Text): False
Whitespace
EndElement
---------- [End Element] ----------
Whitespace
-------------------- 4 --------------------
Element
NODETYPE -- Name: Class
Class: ClassB
Attribute [Name] = ClassB
Whitespace
-------------------- 5 --------------------
Element
NODETYPE -- Name: Property
Property: Property2
Attribute [Name] = Property2
Attribute [dType] = SortedList`2
Attribute [Value] = String
Attribute [Key] = Int16
Whitespace
-------------------- 6 --------------------
Element
NODETYPE -- Name: SrtLstItm
SrtLstItm Key: 1
Attribute [Key] = 1
Text
(Text): 94
Whitespace
EndElement
---------- [End Element] ----------
Whitespace
-------------------- 7 --------------------
Element
NODETYPE -- Name: Property
Property: Property3
Attribute [Name] = Property3
Attribute [dType] = Int32
Text
(Text): 1
Whitespace
-------------------- 8 --------------------
Element
NODETYPE -- Name: Property
Property: Property4
Attribute [Name] = Property4
Attribute [dType] = List`1
Attribute [Type] = Product
Whitespace
-------------------- 9 --------------------
Element
NODETYPE -- Name: LstItm
LstItm: Name=Property4
Attribute [Name] = Property4
Text
(Text): LstItm1
Whitespace
-------------------- 10 --------------------
Element
NODETYPE -- Name: LstItm
LstItm: Name=Property4
Attribute [Name] = Property4
Text
(Text): LstItm2
Whitespace
EndElement
---------- [End Element] ----------
Whitespace
EndElement
---------- [End Element] ----------
Whitespace
-------------------- 11 --------------------
Element
NODETYPE -- Name: Class
Class: ClassC
Attribute [Name] = ClassC
Whitespace
-------------------- 12 --------------------
Element
NODETYPE -- Name: Property
Property: Property5
Attribute [Name] = Property5
Attribute [dType] = String
Text
(Text): 50.5
Whitespace
EndElement
---------- [End Element] ----------
Whitespace
EndElement
---------- [End Element] ----------

请注意,可能并不总是需要InnerText,例如具有LstItm属性的Property。但是,这应该让你开始寻找你需要的东西。

相关问题