[英]Storing Attributes on XML in 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
這是將XmlTextReader與linq結合使用的簡單得多的方法
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
使用您的示例,我提出了兩種遍歷DOM的方法。 第一個使用XmlDocument,第二個使用XmlTextReader。 我將兩者都放入一個將信息輸出到TextBox的示例中。 我這樣做是為了防止您發現使用XmlDocument來跟蹤您所處的級別更容易。 在任何一種情況下,您都需要捕獲每個唯一元素(類,屬性,屬性子級等)的開始並相應地使用。
這是我創建的用於解析文件的單個子文件:
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。 但是,這應該使您開始尋找所需的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.