我正在尝试在VB.NET中阅读以下XML文件
<?xml version="1.0" encoding="UTF-8"?>
<mame build="0.129 (Jan 8 2009)" debug="no">
<game name="puckman" sourcefile="pacman.c">
<description>PuckMan (Japan set 1, Probably Bootleg)</description>
<year>1980</year>
<manufacturer>Namco</manufacturer>
<rom name="namcopac.6e" size="4096" crc="fee263b3" sha1="87117ba5082cd7a615b4ec7c02dd819003fbd669" region="main" offset="0"/>
<rom name="namcopac.6f" size="4096" crc="39d1fc83" sha1="326dbbf94c6fa2e96613dedb53702f8832b47d59" region="main" offset="1000"/>
<rom name="namcopac.6h" size="4096" crc="02083b03" sha1="7e1945f6eb51f2e51806d0439f975f7a2889b9b8" region="main" offset="2000"/>
<rom name="namcopac.6j" size="4096" crc="7a36fe55" sha1="01b4c38108d9dc4e48da4f8d685248e1e6821377" region="main" offset="3000"/>
<rom name="pacman.5e" size="4096" crc="0c944964" sha1="06ef227747a440831c9a3a613b76693d52a2f0a9" region="gfx1" dispose="yes" offset="0"/>
<rom name="pacman.5f" size="4096" crc="958fedf9" sha1="4a937ac02216ea8c96477d4a15522070507fb599" region="gfx1" dispose="yes" offset="1000"/>
<rom name="82s123.7f" size="32" crc="2fc650bd" sha1="8d0268dee78e47c712202b0ec4f1f51109b1f2a5" region="proms" offset="0"/>
<rom name="82s126.4a" size="256" crc="3eb3a8e4" sha1="19097b5f60d1030f8b82d9f1d3a241f93e5c75d6" region="proms" offset="20"/>
<rom name="82s126.1m" size="256" crc="a9cc86bf" sha1="bbcec0570aeceb582ff8238a4bc8546a23430081" region="namco" offset="0"/>
<rom name="82s126.3m" size="256" crc="77245b66" sha1="0c4d0bee858b97632411c440bea6948a74759746" region="namco" offset="100"/>
<chip type="cpu" tag="main" name="Z80" clock="3072000"/>
<chip type="audio" tag="namco" name="Namco" clock="96000"/>
<display type="raster" rotate="90" width="288" height="224" refresh="60.606061" pixclock="6144000" htotal="384" hbend="0" hbstart="288" vtotal="264" vbend="0" vbstart="224" />
<sound channels="1"/>
<input players="2" buttons="1" coins="2" service="yes">
<control type="joy4way"/>
</input>
<dipswitch name="Rack Test (Cheat)">
<dipvalue name="Off" default="yes"/>
<dipvalue name="On"/>
</dipswitch>
<dipswitch name="Service Mode">
<dipvalue name="Off" default="yes"/>
<dipvalue name="On"/>
</dipswitch>
<dipswitch name="Cabinet">
<dipvalue name="Upright" default="yes"/>
<dipvalue name="Cocktail"/>
</dipswitch>
<dipswitch name="Coinage">
<dipvalue name="2 Coins/1 Credit"/>
<dipvalue name="1 Coin/1 Credit" default="yes"/>
<dipvalue name="1 Coin/2 Credits"/>
<dipvalue name="Free Play"/>
</dipswitch>
<dipswitch name="Lives">
<dipvalue name="1"/>
<dipvalue name="2"/>
<dipvalue name="3" default="yes"/>
<dipvalue name="5"/>
</dipswitch>
<dipswitch name="Bonus Life">
<dipvalue name="10000" default="yes"/>
<dipvalue name="15000"/>
<dipvalue name="20000"/>
<dipvalue name="None"/>
</dipswitch>
<dipswitch name="Difficulty">
<dipvalue name="Normal" default="yes"/>
<dipvalue name="Hard"/>
</dipswitch>
<dipswitch name="Ghost Names">
<dipvalue name="Normal" default="yes"/>
<dipvalue name="Alternate"/>
</dipswitch>
<driver status="good" emulation="good" color="good" sound="good" graphic="good" savestate="supported" palettesize="512"/>
</game>
<game name="puckmana" sourcefile="pacman.c" cloneof="puckman" romof="puckman">
<description>PuckMan (Japan set 2)</description>
<year>1980</year>
<manufacturer>Namco</manufacturer>
<rom name="pacman.6e" size="4096" crc="c1e6ab10" sha1="e87e059c5be45753f7e9f33dff851f16d6751181" region="main" offset="0"/>
<rom name="pacman.6f" size="4096" crc="1a6fb2d4" sha1="674d3a7f00d8be5e38b1fdc208ebef5a92d38329" region="main" offset="1000"/>
<rom name="pacman.6h" size="4096" crc="bcdd1beb" sha1="8e47e8c2c4d6117d174cdac150392042d3e0a881" region="main" offset="2000"/>
<rom name="prg7" size="2048" crc="b6289b26" sha1="d249fa9cdde774d5fee7258147cd25fa3f4dc2b3" region="main" offset="3000"/>
<rom name="prg8" size="2048" crc="17a88c13" sha1="eb462de79f49b7aa8adb0cc6d31535b10550c0ce" region="main" offset="3800"/>
<rom name="chg1" size="2048" crc="2066a0b7" sha1="6d4ccc27d6be185589e08aa9f18702b679e49a4a" region="gfx1" dispose="yes" offset="0"/>
<rom name="chg2" size="2048" crc="3591b89d" sha1="79bb456be6c39c1ccd7d077fbe181523131fb300" region="gfx1" dispose="yes" offset="800"/>
<rom name="pacman.5f" merge="pacman.5f" size="4096" crc="958fedf9" sha1="4a937ac02216ea8c96477d4a15522070507fb599" region="gfx1" dispose="yes" offset="1000"/>
<rom name="82s123.7f" merge="82s123.7f" size="32" crc="2fc650bd" sha1="8d0268dee78e47c712202b0ec4f1f51109b1f2a5" region="proms" offset="0"/>
<rom name="82s126.4a" merge="82s126.4a" size="256" crc="3eb3a8e4" sha1="19097b5f60d1030f8b82d9f1d3a241f93e5c75d6" region="proms" offset="20"/>
<rom name="82s126.1m" merge="82s126.1m" size="256" crc="a9cc86bf" sha1="bbcec0570aeceb582ff8238a4bc8546a23430081" region="namco" offset="0"/>
<rom name="82s126.3m" merge="82s126.3m" size="256" crc="77245b66" sha1="0c4d0bee858b97632411c440bea6948a74759746" region="namco" offset="100"/>
<chip type="cpu" tag="main" name="Z80" clock="3072000"/>
<chip type="audio" tag="namco" name="Namco" clock="96000"/>
<display type="raster" rotate="90" width="288" height="224" refresh="60.606061" pixclock="6144000" htotal="384" hbend="0" hbstart="288" vtotal="264" vbend="0" vbstart="224" />
<sound channels="1"/>
<input players="2" buttons="1" coins="2" service="yes">
<control type="joy4way"/>
</input>
<dipswitch name="Rack Test (Cheat)">
<dipvalue name="Off" default="yes"/>
<dipvalue name="On"/>
</dipswitch>
<dipswitch name="Service Mode">
<dipvalue name="Off" default="yes"/>
<dipvalue name="On"/>
</dipswitch>
<dipswitch name="Cabinet">
<dipvalue name="Upright" default="yes"/>
<dipvalue name="Cocktail"/>
</dipswitch>
<dipswitch name="Coinage">
<dipvalue name="2 Coins/1 Credit"/>
<dipvalue name="1 Coin/1 Credit" default="yes"/>
<dipvalue name="1 Coin/2 Credits"/>
<dipvalue name="Free Play"/>
</dipswitch>
<dipswitch name="Lives">
<dipvalue name="1"/>
<dipvalue name="2"/>
<dipvalue name="3" default="yes"/>
<dipvalue name="5"/>
</dipswitch>
<dipswitch name="Bonus Life">
<dipvalue name="10000" default="yes"/>
<dipvalue name="15000"/>
<dipvalue name="20000"/>
<dipvalue name="None"/>
</dipswitch>
<dipswitch name="Difficulty">
<dipvalue name="Normal" default="yes"/>
<dipvalue name="Hard"/>
</dipswitch>
<dipswitch name="Ghost Names">
<dipvalue name="Normal" default="yes"/>
<dipvalue name="Alternate"/>
</dipswitch>
<driver status="good" emulation="good" color="good" sound="good" graphic="good" savestate="supported" palettesize="512"/>
</game>
</mame>
这是我使用的代码
Imports System.IO
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
Dim m_xmld As XmlDocument
Dim m_nodelist As XmlNodeList
Dim m_node As XmlNode
m_xmld = New XmlDocument()
m_xmld.Load("C:\mame2.xml")
m_nodelist = m_xmld.SelectNodes("/mame/game")
For Each m_node In m_nodelist
Dim GameAttribute = m_node.Attributes.GetNamedItem("name").Value
Dim name = m_node.ChildNodes.Item(0).InnerText
Dim description = m_node.ChildNodes.Item(1).InnerText
Dim manufacturer = m_node.ChildNodes.Item(2).InnerText
Dim rotate = m_node.ChildNodes.Item(15).Attributes.GetNamedItem("rotate").Value
Dim controles = m_node.ChildNodes.Item(17).ChildNodes.Item(0).Attributes.GetNamedItem("type").Value
MessageBox.Show("ROM: " & GameAttribute _
& "-- Description: " & name & "-- Year: " _
& description & "-- Manufacturer: " _
& manufacturer & "-- Rotate: " _
& rotate & "-- Control Type: " & controles)
Next
Catch errorVariable As Exception
MessageBox.Show(errorVariable.ToString())
End Try
Me.Close()
End Sub
End Class
我正在尝试阅读“名称”,“描述”,“年份”,“制造商”,“旋转”和“输入播放器控件类型”。
使用此代码,我可以阅读第一个游戏,但不能阅读XML文件的其余部分(在本例中我粘贴了2个游戏)。我可以通过childnode编号读取Childnodes和atributes,问题是“rom”中的游戏有不同数量的子节点,程序返回错误。
我想有另一种阅读本文的方法,但我不知道是哪一种。
感谢您提前和抱歉我的英语。
答案 0 :(得分:1)
您需要使用XPath而不是索引按名称访问子节点。例如:
Dim name As String = m_node.SelectSingleNode("@name").InnerText
Dim description As String = m_node.SelectSingleNode("description").InnerText
Dim manufacturer As String = m_node.SelectSingleNode("manufacturer").InnerText
Dim rotate As String = m_node.SelectSingleNode("display/@rotate").InnerText
Dim controls As String = m_node.SelectSingleNode("input/control/@type").InnerText
答案 1 :(得分:0)
这应该可以解决问题,尽管我确实对你试图反序列化的对象类型采取了一些自由。还有一些工作要做(如'TODO'所述)。我遗漏的唯一代码是将文件路径解析为流以传递给主类的serialize / desreialize方法。我希望这会有所帮助。
#Region "Imports"
'first, import some usefull namespaces
Imports System
Imports System.IO
Imports System.Xml.Serialization
#End Region
#Region "Classes"
'then, start constructing your classes by drilling down in sequence
''' <summary>
''' A class to hold your xml file's data.
''' </summary>
''' <remarks>This class will hold the the data from your file.</remarks>
<XmlRoot("mame")> _
Public Class YourXML_File
#Region "Properties"
<XmlAttribute(AttributeName:="build")> _
Public Property Build As String
<XmlAttribute(AttributeName:="debug")> _
Public Property Debug As New StrangeBooleanNomenclatureType
<XmlArray(ElementName:="game")> _
Public Property Games As New List(Of Game)
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#Region "XML Serialization / Deserialization"
''' <summary>
''' Strongly typed method to serialize your object.
''' </summary>
Public Shared Function Serialize(ByVal astream As Stream, ByVal axml_fileobj As YourXML_File) As Boolean
'try to serialize the file stream
Try
'first create a xml serializer object
Dim serializer As New XmlSerializer(GetType(YourXML_File))
'then serialize the object
serializer.Serialize(astream, axml_fileobj)
'return a successful serialization
Return True
Catch ex As Exception
'TODO: handle any exceptions here as you wish
'let the calling method know the serialization failed
Return False
End Try
End Function
''' <summary>
''' Strongly typed method to deserialize your object
''' </summary>
Public Shared Function Deserialize(ByVal astream As Stream, ByVal axml_fileobj As YourXML_File) As Boolean
'try to deserialize the file stream
Try
'first create a xml serializer object
Dim serializer As New XmlSerializer(GetType(YourXML_File))
'then deserialize the object
axml_fileobj = serializer.Deserialize(astream)
'return a successful deserialization
Return True
Catch ex As Exception
'TODO: handle any exceptions here as you wish
'let the calling method know the deserialization failed
Return False
End Try
End Function
#End Region
#End Region
End Class
''' <summary>
''' A class to represent the "game" element.
''' </summary>
<XmlRoot("game")> _
Public Class Game
#Region "Properties"
<XmlAttribute("name")> _
Public Property Game_Name As String
<XmlAttribute("sourcefile")> _
Public Property Game_SourceFile As String
<XmlElement("description")> _
Public Property Game_Description As String
<XmlElement("year")> _
Public Property Game_Year As Integer
<XmlElement("manufacture")> _
Public Property Game_Manufacturer As String
<XmlElement("roms")> _
Public Property Game_Roms As New List(Of Rom)
<XmlElement("chips")> _
Public Property Game_Chips As New List(Of Chip)
<XmlElement("display")> _
Public Property Game_Display As New Display
<XmlElement("sound")> _
Public Property Game_Sound As New Sound
<XmlElement("input")> _
Public Property Game_Input As New Input
<XmlElement("dipswitches")> _
Public Property Game_Dipswitches As New List(Of DipSwitch)
<XmlElement("driver")> _
Public Property Game_Driver As New Driver
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("rom")> _
Public Class Rom
#Region "Properties"
<XmlAttribute("name")> _
Public Property Rom_Name As String
<XmlAttribute("size")> _
Public Property Rom_Size As Integer
<XmlAttribute("crc")> _
Public Property Rom_Crc As String
<XmlAttribute("sha1")> _
Public Property Rom_Sha1 As String
<XmlAttribute("region")> _
Public Property Rom_Region As New RomRegionType
<XmlAttribute("dispose")> _
Public Property Rom_Dispose As New StrangeBooleanNomenclatureType
<XmlAttribute("offset")> _
Public Property Rom_Offset As Integer
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("chip")> _
Public Class Chip
#Region "Properties"
<XmlAttribute("type")> _
Public Property Chip_Type As New ChipType
<XmlAttribute("tag")> _
Public Property Chip_Tag As String
<XmlAttribute("name")> _
Public Property Chip_Name As String
<XmlAttribute("clock")> _
Public Property Chip_Clock As Integer
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("display")> _
Public Class Display
#Region "Properties"
<XmlAttribute("type")> _
Public Property Display_Type As New DisplayType
<XmlAttribute("rotate")> _
Public Property Display_Rotate As Integer
<XmlAttribute("width")> _
Public Property Display_Width As Integer
<XmlAttribute("height")> _
Public Property Display_Height As Integer
<XmlAttribute("refresh")> _
Public Property Display_Refresh As Double
<XmlAttribute("pixclock")> _
Public Property Display_PixClock As Integer
<XmlAttribute("htotal")> _
Public Property Display_H_Total As Integer
<XmlAttribute("hbend")> _
Public Property Display_H_Bend As Integer
<XmlAttribute("hbstart")> _
Public Property Display_HbStart As Integer
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("sound")> _
Public Class Sound
#Region "Properties"
<XmlAttribute("channels")> _
Public Property Sound_Channels As Integer
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("input")> _
Public Class Input
#Region "Properties"
<XmlAttribute("players")> _
Public Property Input_Players As Integer
<XmlAttribute("buttons")> _
Public Property Input_Buttons As Integer
<XmlAttribute("coins")> _
Public Property Input_Coins As Integer
<XmlAttribute("service")> _
Public Property Input_Service As New StrangeBooleanNomenclatureType
<XmlElement("control")> _
Public Property Input_Controls As New List(Of Control)
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("control")> _
Public Class Control
#Region "Properties"
<XmlAttribute("type")> _
Public Property Control_Type As New ControlType
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("dipswitch")> _
Public Class DipSwitch
#Region "Properties"
<XmlAttribute("name")> _
Public Property DipSwitch_Name As String
<XmlElement("dipvalue")> _
Public Property DipSwitch_DipValues As New List(Of DipValue)
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("dipvalue")> _
Public Class DipValue
#Region "Properties"
<XmlAttribute("name")> _
Public Property DipValue_Name As String
<XmlAttribute("default")> _
Public Property DipValue_Default As New StrangeBooleanNomenclatureType
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
<XmlRoot("driver")> _
Public Class Driver
#Region "Properties"
<XmlAttribute("status")> _
Public Property Driver_Status As New StatusState
<XmlAttribute("emulation")> _
Public Property Driver_Emulation As New StatusState
<XmlAttribute("color")> _
Public Property Driver_Color As New StatusState
<XmlAttribute("sound")> _
Public Property Driver_Sound As New StatusState
<XmlAttribute("graphic")> _
Public Property Driver_Graphic As New StatusState
<XmlAttribute("savestate")> _
Public Property Driver_SaveState As New SaveStateType
<XmlAttribute("palettesize")> _
Public Property Driver_PaletteSize As Integer
#End Region
#Region "Methods"
#Region "Constructors"
''' <summary>
''' The default constructor.
''' </summary>
''' <remarks>The xml serializer requires a constructor which takes no arguments.</remarks>
Public Sub New()
'do stuff here if you need to, but try to relegate anything important to a constructor that takes a parameter accommodating said important behavior
End Sub
#End Region
#End Region
End Class
#End Region
#Region "Enums"
'finally, introduce some enumerations to strongly define the exact range of the more loosely defined attributes used
Public Enum StatusState
<XmlEnum("bad")> Bad = 0
<XmlEnum("good")> Good = 1
End Enum
Public Enum StrangeBooleanNomenclatureType
<XmlEnum("no")> No = 0
<XmlEnum("yes")> Yes = 1
End Enum
Public Enum ChipType
<XmlEnum("cpu")> CPU = 0
<XmlEnum("audio")> Audio = 1
'TODO: add other chip types here
End Enum
Public Enum RomRegionType
<XmlEnum("main")> Main = 0
<XmlEnum("gfx1")> GFX1 = 1
<XmlEnum("proms")> Proms = 2
<XmlEnum("namco")> Namco = 3
'TODO: add more region types here
End Enum
Public Enum DisplayType
<XmlEnum("raster")> Raster = 0
'TODO: add more display types here
End Enum
Public Enum ControlType
<XmlEnum("joy4way")> joy4way = 0
'TODO: add more control types here
End Enum
Public Enum SaveStateType
<XmlEnum("supported")> Supported = 0
'TODO: add more save state types here
End Enum
#End Region