我使用这种通用格式创建了一个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
答案 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。但是,这应该让你开始寻找你需要的东西。