使用 LINQ to XML 进行 MP3 标签 XML 写入器和 XSD 验证
创建 MP3 标签 XML 文件并对其进行验证。
- 下载源代码 - 394.82 KB
在下载此应用程序之前,请阅读“要点”中的更新,第二段。
引言
我使用记事本已经有一段时间了,并用它来创建各种类型的文件。我最近想为我的 MP3 收藏创建一个 XML 文件,发现为 350 多个 MP3 文件编写 5 到 8 个标签将是一项艰巨的任务(对我来说,打字就是一项任务)。所以,我决定创建一个程序来完成这项工作,并将验证作为额外的功能。
在我上大学的时候(大约 20 年前),我们的教授总是让我们在创建程序时使用某种伪代码来遵循,我完全忘记了它,直到我决定制作这个程序。
这是伪代码……短版本
- 设计用户界面(使用下面的伪代码)
- 创建一个带有XML扩展名的文件名
- 验证,然后如果文件名有效则接受
- 选择 MP3 并将它们添加到列表框
- 创建标签并将其写入文件
- 在列表框中向用户显示我们迄今为止所做的工作
- 使用 XSD(LINQ to XML)验证文件
- 验证后,打开文件查看我们的成果
- 最后……重置,如果需要,重复
起点
XML 写入器开始时,所有按钮都处于禁用状态。您必须完成第一个任务才能继续下一个任务。在创建文件名、验证文件名、选择 MP3 并写入标签后,我们现在进入验证部分。我们现在可以验证我们刚刚创建的文件。
Private Sub buttonValidate_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles buttonValidate.Click
lstActions.Items.Add("Linking (LINQ to XML using XSD)")
'XSD code was in ms-help
'I re-edited it to fit the output in the xml file
Dim xsdMarkup As XElement = _
<schema xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" />
<element name=""MP3Info"" />
<complextype />
<sequence maxoccurs=""unbounded"" />
<element name=""TrackTitle"" type=""xsd:string"" />
<element name=""Artist"" type=""xsd:string"" />
<element name=""Length"" type=""xsd:string"" />
<element name=""Title"" type=""xsd:string"" />
<element name=""Genre"" type=""xsd:string"" />
</sequence />
</complextype />
</element />
</schema />
Dim schemas As XmlSchemaSet = New XmlSchemaSet()
schemas.Add("", xsdMarkup.CreateReader)
lstActions.Items.Add("Attempting to Validate")
Dim myDoc As XDocument = XDocument.Load(path & Trim(txtFileXML.Text))
errors = False
myDoc.Validate(schemas, AddressOf XSDErrors)
If errors = True Then
isValid = False
lstActions.Items.Add("File is InValid")
lblStatus.Text = "Invalid..."
buttonOpen.Enabled = True
Exit Sub
Else
isValid = True
lstActions.Items.Add("File is Valid")
lblStatus.Text = "Valid..."
End If
buttonOpen.Enabled = True
End Sub
我在 MS-Help 中搜索了代码,但只找到了旧代码,这些代码与 .NET 3.5 版本不太兼容。大多数代码都是为 .NET 1.1 版本编写的,后来我因为代码错误才发现这一点。我还发现使用 XML 时不允许出现错误。如果出现错误,您的程序就会崩溃。因此,您必须编写无错误的代码,我通过反复试验,使用我在 MS-Help 中找到的各种小技巧,最终完成了这项工作。
Private Sub loadFiles(ByVal mediaType As String)
Dim supportedFiles As String
Select Case mediaType
Case "Audio"
supportedFiles = audioFiles
Case Else
supportedFiles = audioFiles
End Select
lstActions.Items.Add("Please wait...Creating File")
With ofd 'OpenFileDialog Control
.InitialDirectory = strPath
.Filter = supportedFiles
.CheckFileExists = True
.Multiselect = True
.RestoreDirectory = True
End With
If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
Using sw As StreamWriter = File.CreateText(path & Trim(txtFileXML.Text))
sw.WriteLine("")
sw.WriteLine("<mp3info />") 'Opening Tag for MP3Info
For Each Me.strFilePath In ofd.FileNames
strFileShow = GetFileName(strFilePath)
lstMP3.Items.Add(strFilePath)
MMedia.LoadMedia(strFilePath)
Dim fileInfo As New clsID3v1Reader(strFilePath)
'sw.WriteLine("<mp3info />") 'Opening Tag for MP3Info
sw.WriteLine(" <tracktitle />" & fileInfo.TrackTitle & _
"</tracktitle />")
sw.WriteLine(" <artist />" & fileInfo.Artist & "</artist />")
'Lets get the time length of the mp3 file.
Dim secx, minx, mediaTotal As String
Dim mediaTimes As String
mediaTotal = CStr(Int(MMedia.MediaDuration))
'If mediaTotal < 1 Then mediaTotal = 1
secx = CStr(CDbl(mediaTotal) - (Int(CDbl(mediaTotal) / 60) * 60))
minx = CStr(Int((CDbl(mediaTotal) -
Int(CDbl(mediaTotal) / 3600) * 3600) / 60))
mediaTimes = minx.ToString() & ":" & secx.ToString
sw.WriteLine(" <length />" & mediaTimes & "</length />")
MMedia.UnLoadMedia(strFilePath)
sw.WriteLine(" ")
sw.WriteLine(" <genre />" & GetGenre(currentMP3) & "</genre />")
'sw.WriteLine("</mp3info />") 'Closing Tag for MP3Info
sw.WriteLine()
Next
sw.WriteLine("</mp3info />") 'Closing Tag for MP3Info
'Lets close the writer.
sw.Close()
End Using
End If
'Display again what we are doing for the user...
lstActions.Items.Add("File created - " & Trim(txtFileXML.Text))
lstActions.Items.Add("# of files selected..." & (lstMP3.Items.Count).ToString)
lblStatus.Text = (lstMP3.Items.Count).ToString & " files selected"
'Make unenabled, Enabled.
buttonValidate.Enabled = True
End Sub
接下来……我们可以打开我们刚刚创建的新文件来查看我们辛勤工作的成果。我使用了Process
类来打开记事本并显示我们的文件。
Private Sub buttonOpen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles buttonOpen.Click
ProcessNotepad.StartInfo.FileName = path & Trim(txtFileXML.Text)
ProcessNotepad.Start()
ProcessNotepad.WaitForExit()
buttonReset.Enabled = True
End Sub
Using the Code
XML 写入器创建的mp3tag.xml文件可以用作 WPF 或 Blend 的数据源、播放列表,或 XML 文件可以用于的其他任何用途。我认为它是一个很好的实用工具,但那只是我的一厢情愿。
我在这个程序中使用的类是在此网站和 MS-Help 上找到的已重新编辑的类。clsDirectXAudio.vb来自 MMPlayer,可以在此网站上找到;clsID3TagReader.vb我认为在“Managing a MP3 Collection”中,该文件在 MS-Help 上是 MS-Word 文档格式。最后一点,程序不能在 IDE 中运行,它会抛出托管代码异常。制作一个.exe文件并在 IDE 外运行,它就可以正常工作。
关注点
当我刚开始这个项目时,我对 LINQ、XSD 或 XML 一无所知,现在我比开始时知道得更多了(开始时我脑袋里空空如也)。
在我修复一些错误之前,请不要下载。我完全忘记了撇号、和号以及小于号和大于号。我不知道如何在string
中读取字符,即使我找到了方法,也不知道如何使用代码(最好是 VB.NET)替换它们。感谢您的耐心等待。如果有人能指出我正确的方向,我将不胜感激!
更新
在原始的XMLWriter
中,存在设计缺陷,导致了一些棘手的异常。当遇到和号或撇号时,它会抛出异常。我通过在正确的位置进行几次替换操作来修复它。我还重新编写了隐藏在程序中作为标签的伪代码。请看下面的图片。
Using the Code
程序启动后(介绍图片),您将输入一个带有 XML 扩展名的文件名,然后按接受按钮(上图)。接下来...
输入任意数量的 MP3 文件,程序将创建您的 XML 文件并将其显示在listbox
中。上图。接下来...
我们验证新创建的 XML 文件。通过在正确的位置使用几次替换操作,这解决了在选择带有 ampersands 或 apostrophies 的 MP3 文件(例如:Brooks & Dunn - She's not the cheatin' Kind)的 tracktitle、title 或 artist 时发生的异常。这会导致程序崩溃。现在已经修复。上图。接下来……只需按下重置按钮,您就可以重新开始所有操作。多次执行此操作作为 WPF® 或 Blend® 的播放列表很有用。下图。
全体致歉
如果您下载了原始的XMLWriter
,请将其删除并使用此更新版本。它的工作效果更好,结果也更好。对于我这个小小的思维失误可能给您带来的任何不便,我深表歉意。再次……全体致歉。
致作者…
对于我使用的代码的所有作者(所有姓名都在程序注释中),我非常感谢大家。特别感谢 MS-Help 拥有如此庞大的知识库。