Wordnet 合理改造





5.00/5 (4投票s)
XML 文件的字符串操作。
引言
在本文中,我将展示一些通过操作字符串值来处理 XML 元素的技术。
背景
有一天,一位朋友来访,问我是否知道他 iPad 上的词典。他告诉我,他的 iPad 上有一个词典,里面提供的例句与词头不符。我曾花了一些时间研究 Wordnet 数据库文件,于是我说:“我完全知道发生了什么!”你们也一样:但首先,这是背景介绍。
Wordnet 是普林斯顿大学运营的一个词汇项目。他们有一个非常大的词汇数据库,并且可以 在此处下载。如果您想运行该项目,则需要此数据库。如果您想了解更多关于 Wordnet 的信息,请访问他们的网站。解决 iPad 上的词典例句错误的钥匙在于 Wordnet XML 数据库的结构。
此项目根据 CPOL 发布。但是,WordNet 有自己的 许可证,其使用条款应被理解和遵守。
以下是 WordNet 数据库中一个元素的摘录。它包含了上面“结构”中所述的所有 synset
数据。
<synset pos="r" ofs="00516492" id="r00516492">
<terms><term>wrongfully</term></terms>
<keys><sk>wrongfully%4:02:00::</sk></keys>
<gloss desc="orig">
<orig>in an unjust or unfair manner; "the employee claimed that she was
wrongfully dismissed"; "people who were wrongfully imprisoned should be
released"</orig>
</gloss>
<gloss desc="text">
<text>in an unjust or unfair manner ; â the employee claimed that she was
wrongfully dismissed â ; â people who were wrongfully imprisoned should be
released â</text>
</gloss>
<gloss desc="wsd">
<def id="r00516492_d">
<wf pos="IN" id="r00516492_wf1" tag="ignore"
lemma="in">in</wf>
<wf pos="DT" id="r00516492_wf2" tag="ignore"
lemma="an">an</wf>
<wf pos="JJ" id="r00516492_wf3" tag="man"
lemma="unjust%3">
<id id="r00516492_id.6" lemma="unjust" sk="unjust
%3:00:02::"/>
<id id="r00516492_id.5" lemma="unjust" sk="unjust
%3:00:04::"/>
<id id="r00516492_id.4" lemma="unjust" sk="unjust
%3:00:00::"/>unjust</wf>
<wf pos="CC" id="r00516492_wf4" tag="ignore"
lemma="or">or</wf>
<wf pos="JJ" id="r00516492_wf5" tag="man"
lemma="unfair%3">
<id id="r00516492_id.8" lemma="unfair" sk="unfair
%3:00:00::"/>unfair</wf>
<wf pos="NN" id="r00516492_wf6" tag="man"
lemma="manner%1" sep="">
<id id="r00516492_id.7" lemma="manner" sk="manner
%1:07:02::"/>manner</wf>
<wf pos=":" id="r00516492_wf7" tag="ignore"
type="punc">;</wf>
</def><ex id="r00516492_ex1"><qf rend="dq">
<wf id="r00516492_wf8" tag="ignore"
lemma="the">the</wf>
<wf id="r00516492_wf9" tag="un" lemma="employee
%1">employee</wf>
<wf id="r00516492_wf10" tag="un" lemma="claim
%2">claimed</wf>
<wf id="r00516492_wf11" tag="ignore"
lemma="that">that</wf>
<wf id="r00516492_wf12" tag="ignore"
lemma="she">she</wf>
<wf id="r00516492_wf13" tag="un" lemma="be
%2">was</wf>
<wf id="r00516492_wf14" tag="auto" lemma="wrongfully
%4">
<id id="r00516492_id.2" lemma="wrongfully" sk="wrongfully
%4:02:00::"/>wrongfully</wf>
<wf id="r00516492_wf15" tag="un" lemma="dismiss%2|dismissed
%3" sep="">dismissed</wf>
</qf>
<wf id="r00516492_wf16" tag="ignore"
type="punc">;</wf>
</ex><ex id="r00516492_ex2"><qf rend="dq">
<wf id="r00516492_wf17" tag="un" lemma="people%1|people
%2">people</wf>
<wf id="r00516492_wf18" tag="ignore"
lemma="who">who</wf>
<wf id="r00516492_wf19" tag="un" lemma="be
%2">were</wf>
<wf id="r00516492_wf20" tag="auto" lemma="wrongfully
%4">
<id id="r00516492_id.3" lemma="wrongfully" sk="wrongfully
%4:02:00::"/>wrongfully</wf>
<wf id="r00516492_wf21" tag="un" lemma="imprison%2|imprisoned
%3">imprisoned</wf>
<wf id="r00516492_wf22" tag="ignore"
lemma="should">should</wf>
<wf id="r00516492_wf23" tag="un" lemma="be
%2">be</wf>
<wf id="r00516492_wf24" tag="un" lemma="release%2"
sep="">released</wf>
</qf>
<wf id="r00516492_wf25" tag="ignore"
type="punc">;</wf>
</ex>
</gloss>
</synset>
但我只需要一个词典,而不是所有这些花哨的交叉引用元素。以编程方式从这个示例元素中提取我想要的内容,将生成一个类似以下的词典条目:
那没什么问题。但等等,我朋友的 iPad 呢?好吧,让我们看看从 XML 文件中提取的另一个 synset
元素。从结构可以看出,<terms>
元素中有 3 个 <term>
元素。
<synset id="v00384055" ofs="00384055" pos="v">
<terms>
<term>metamorphose</term>
<term>transfigure</term>
<term>transmogrify</term>
</terms>
<keys>
<sk>metamorphose%2:30:00::</sk>
<sk>transfigure%2:30:00::</sk>
<sk>transmogrify%2:30:00::</sk>
</keys>
<gloss desc="orig">
<orig>change completely the nature or appearance of; "In
Kafka's story, a person metamorphoses into a bug"; "The treatment and diet
transfigured her into a beautiful young woman"; "Jesus was transfigured after
his resurrection"</orig>
</gloss>
<gloss desc="text">
<text>change completely the nature or appearance of ; â In
Kafka's story , a person metamorphoses into a bug â ; â The treatment and
diet transfigured her into a beautiful young woman â ; â Jesus was
transfigured after his resurrection â</text>
</gloss>
<gloss desc="wsd">
<def id="v00384055_d">
<wf id="v00384055_wf1" lemma="change%1|change%2"
pos="VB" tag="man">
<id id="v00384055_id.5" lemma="change"
sk="change%2:30:01::"/>change</wf>
<wf id="v00384055_wf2" lemma="completely%4"
pos="RB" tag="un">completely</wf>
<wf id="v00384055_wf3" lemma="the"
pos="DT" tag="ignore">the</wf>
<wf id="v00384055_wf4" lemma="nature%1"
pos="NN" tag="un">nature</wf>
<wf id="v00384055_wf5" lemma="or"
pos="CC" tag="ignore">or</wf>
<wf id="v00384055_wf6" lemma="appearance%1"
pos="NN" tag="man">
<id id="v00384055_id.4" lemma="appearance"
sk="appearance%1:07:00::"/>appearance</wf>
<wf id="v00384055_wf7" lemma="of"
pos="IN" sep="" tag="ignore">of</wf>
<wf id="v00384055_wf8" pos=":"
tag="ignore" type="punc">;</wf>
</def>
<ex id="v00384055_ex1">
<qf rend="dq">
<wf id="v00384055_wf9" lemma="in"
tag="ignore">In</wf>
<wf id="v00384055_wf10" lemma="Kafka%1"
tag="un">Kafka's</wf>
<wf id="v00384055_wf11" lemma="story%1"
sep="" tag="un">story</wf>
<wf id="v00384055_wf12" tag="ignore"
type="punc">,</wf>
<wf id="v00384055_wf13" lemma="a"
tag="ignore">a</wf>
<wf id="v00384055_wf14" lemma="person%1"
tag="un">person</wf>
<wf id="v00384055_wf15" lemma="metamorphosis
%1|metamorphose%2" tag="auto">
<id id="v00384055_id.1"
lemma="metamorphose" sk="metamorphose
%2:30:00::"/>metamorphoses</wf>
<wf id="v00384055_wf16" lemma="into"
tag="ignore">into</wf>
<wf id="v00384055_wf17" lemma="a"
tag="ignore">a</wf>
<wf id="v00384055_wf18" lemma="bug%1|bug
%2" sep="" tag="un">bug</wf>
</qf>
<wf id="v00384055_wf19" tag="ignore"
type="punc">;</wf>
</ex>
<ex id="v00384055_ex2">
<qf rend="dq">
<wf id="v00384055_wf20" lemma="the"
tag="ignore">The</wf>
<wf id="v00384055_wf21" lemma="treatment
%1" tag="un">treatment</wf>
<wf id="v00384055_wf22" lemma="and"
tag="ignore">and</wf>
<wf id="v00384055_wf23" lemma="diet%1|diet
%2" tag="un">diet</wf>
<wf id="v00384055_wf24" lemma="transfigure
%2" tag="auto">
<id id="v00384055_id.2"
lemma="transfigure" sk="transfigure
%2:30:00::"/>transfigured</wf>
<wf id="v00384055_wf25" lemma="her"
tag="ignore">her</wf>
<wf id="v00384055_wf26" lemma="into"
tag="ignore">into</wf>
<wf id="v00384055_wf27" lemma="a"
tag="ignore">a</wf>
<wf id="v00384055_wf28" lemma="beautiful
%3" tag="un">beautiful</wf>
<wf id="v00384055_wf29" lemma="young%1|young
%3" tag="un">young</wf>
<wf id="v00384055_wf30" lemma="woman%1"
sep="" tag="un">woman</wf>
</qf>
<wf id="v00384055_wf31" tag="ignore"
type="punc">;</wf>
</ex>
<ex id="v00384055_ex3">
<qf rend="dq">
<wf id="v00384055_wf32" lemma="Jesus%1"
tag="un">Jesus</wf>
<wf id="v00384055_wf33" lemma="be%2"
tag="un">was</wf>
<wf id="v00384055_wf34" lemma="transfigure
%2" tag="auto">
<id id="v00384055_id.3"
lemma="transfigure" sk="transfigure
%2:30:00::"/>transfigured</wf>
<wf id="v00384055_wf35" lemma="after%3|after
%4" tag="un">after</wf>
<wf id="v00384055_wf36" lemma="his"
tag="ignore">his</wf>
<wf id="v00384055_wf37" lemma="resurrection
%1" sep="" tag="un">resurrection</wf>
</qf>
<wf id="v00384055_wf38" tag="ignore"
type="punc">;</wf>
</ex>
</gloss>
</synset>
如果我要以编程方式从此元素中提取词典条目,最终的文本将类似于:
transfigure: 完全改变性质或外观;“在卡夫卡的故事中,一个人变成了一只虫子”;“治疗和饮食使她变成了一个年轻美丽的女人”;“耶稣复活后被改变了容貌”
transmogrify: 完全改变性质或外观;“在卡夫卡的故事中,一个人变成了一只虫子”;“治疗和饮食使她变成了一个年轻美丽的女人”;“耶稣复活后被改变了容貌”
前两个几乎都可以,因为它们每个都至少有一个与词头匹配的例子,但“transmogrify”的条目有三个错误的例句。甚至不能安全地尝试替换示例句子中的 <term>
匹配项。如果不目视检查每个句子,您可能会创建诸如“耶稣复活后被 transmogrified 了”这样的例句,这可能在技术上是正确的,但我确定有些人会对此感到冒犯。因此,任何尝试运行简单查询来提取词头、定义和例句的尝试都会产生错误。
Using the Code
要运行代码,您需要下载上面链接中的 WordNet 数据库文件,解压“merged”文件夹,然后将该文件夹放在项目的 debug 文件夹中。我保留了 Console.WriteLine()
,因此运行代码会显示本文中给出的要点和示例,但大多数都会快速闪过,您甚至来不及阅读。因此,如果您想让它在任何一点停止,请在适当的位置插入 Console.Readline()
。按当前发布版本,只有一个在最后。
所有代码都在控制台应用程序中运行。Sub Main
调用子程序,这些子程序演示了不同方式的 string
操作 XML 元素的值和属性。这些子程序在下面描述,但如果您需要查看具体操作,逐步调试代码会更容易。我只显示文章中演示我所说内容的特定要点。
Sub Main()
wrongfully()
Rightfully()
Wordley()
HTML()
End Sub
WordNet Wrongfully()
Transmogrified:展示了如何实现我上面最初描述的错误示例。它会生成一个 XML 文件“wrongfully.xml”。浏览此文件,您只看到 4 个条目就会遇到一个看起来很奇怪的。
<entry>
<hw>dorsal</hw>
<orig>facing away from the axis of an organ or organism;
"the abaxial surface of a leaf is the underside or side facing away from the stem"</orig>
<pos>a</pos>
</entry>
但从积极的一面来看,前三个出来是好的。而“transmogrify”示例的 XML 文件看起来正是我预测的那样,解释了错误的例句是如何出现在 iPad 上的。
<entry>
<hw>metamorphose</hw>
<orig>change completely the nature or appearance of;
"In Kafka's story, a person metamorphoses into a bug";
"The treatment and diet transfigured her into a beautiful young woman";
"Jesus was transfigured after his resurrection"</orig>
<pos>v</pos>
</entry>
<entry>
<hw>transfigure</hw>
<orig>change completely the nature or appearance of;
"In Kafka's story, a person metamorphoses into a bug";
"The treatment and diet transfigured her into a beautiful young woman";
"Jesus was transfigured after his resurrection"</orig>
<pos>v</pos>
</entry>
<entry>
<hw>transmogrify</hw>
<orig>change completely the nature or appearance of;
"In Kafka's story, a person metamorphoses into a bug";
"The treatment and diet transfigured her into a beautiful young woman";
"Jesus was transfigured after his resurrection"</orig>
<pos>v</pos>
</entry>
WordNet Rightfully()
Transmogrified:我想要的是一个 XML 文档,其中包含 Wordnet XML 数据库,但只包含词头、定义、同义词(如果有)的条目,并且如果存在与词头匹配的示例,则包含该示例。只是一个简单的 XML 格式的词典,然后可以将其翻译成其他程序或格式。通过仔细查看数据库中的元素,我发现 <orig>
元素包含适合所有 <term>
值的定义,但之后,它可能包含也可能不包含例句,并且可能不包含适合每个列出的词的示例。因此,我补充说,我不会决定同义词是否可以在例句中替换。我只想要匹配的。
Rightfully()
展示了如何使用 string
操作 WordNet XML 元素,将 WordNet 数据库转换为 XML 格式的词典条目。在此,我从数据库文件中获取 <orig>
元素(您可以在上面的代码示例中看到该元素),其中包含适用于 synset 的定义和示例。
我首先按分号 split
数据,这对大多数元素都有效。我不得不添加 string
replace
来处理那些没有用分号分隔的少数条目。我只需运行它,直到出错,然后找出所需的 string
替换,以处理错误。我使用 replace
在正确的位置添加分号,因此当分号在 split
中被剥离时,文本与之前相同。现在我有了词头和所有可用的例句。我 split
了示例并检查它是否 contains
词头。如果包含,则将其与该词头匹配。
这会生成“transmogrify”示例的条目,其中我已实现了将例句与词头匹配等所需结果。
<!-- note: that each entry only has example sentences in the
q element that apply only to the entry they are in. Note also that
the term elements contain the synonyms for the headword. This is used in the
HTML() sub and stripped out in the Wordley() sub. -->
<entry>
<hw>metamorphose</hw>
<pos>v</pos>
<def>change completely the nature or appearance of</def>
<term>transfigure</term>
<term>transmogrify</term>
<q> "In Kafka's story, a person metamorphoses into a bug"</q>
</entry>
<entry>
<hw>transfigure</hw>
<pos>v</pos>
<def>change completely the nature or appearance of</def>
<term>metamorphose</term>
<term>transmogrify</term>
<q> "The treatment and diet transfigured her into a beautiful young woman"</q>
<q> "Jesus was transfigured after his resurrection"</q>
</entry>
<entry>
<hw>transmogrify</hw>
<pos>v</pos>
<def>change completely the nature or appearance of</def>
<term>metamorphose</term>
<term>transfigure</term>
</entry>
我对结果 XML 文件进行了一些测试,但我无法证明在 rightfully()
中进行 string
替换的过程中有任何错误输入,但我偶然发现了一件事,因为我当时没有留意。至少有一个应该存在的例句丢失了。有些例句将“felt”作为“feel”的过去式,这在使用 contains("feel")
时会丢失。但已经达到了不包含错误输入例句的目标。在复数或过去式不匹配的情况下,我可能丢失了一些。
Wordley()
是一个子程序,它使用 Rightfully()
中创建的 XML 文件来进一步 string
操作 XML 文件,将其转换为与 Alan Burkhart 在其 CP 文章中提供的词典格式完全相同的文本文件:Wordley。唯一的例外是,这会生成完整的数据库转换为词典,而 Wordley 是一个精简版本。我使用 StringBuilder
和 IDictionary
来构建 Wordley 文件。我利用了 IDictionary
不能添加重复键的事实,因此我尝试在 Try
中添加,如果已存在,则转到 Catch
,然后在 Catch
中查找已存在的项并添加到其中。
HTML()
将 Rightfully()
中创建的文件转换为单独的编号 XML 文件,类似于但又不完全相同于 Christ Kennedy 在其 CP 文章 GCIDE: A Complete English Language Dictionary. 中为 XML 词典创建的目录。在我的版本中,我将其设置为每个文件包含同一词头的全部条目,而不是每个定义一个文件。在 Wordley 和 HTML 中,我都利用了 IDictionary
不允许重复键的事实,将此放在 Try
- Catch
中。首先,它尝试为下一个元素的词头创建一个键。如果它尚不存在,则执行此操作。否则,它转到 catch,在那里我使其查找已存在的项并添加到其中。如果您不想查看 XML 文件和样式表以及它们如何协同工作,我建议注释掉 HTML()
子程序,因为它将创建 147,306 个 XML 文件,占用约 600 MB 的磁盘空间。如果您只想查看其中的几个以及它们如何工作,可以在 HTML()
子程序开始运行后随时停止项目,因为 XSL 样式表已就位。然后,如果您双击一个 XML 文件,它将在您的 Web 浏览器中打开,但它将是随机选择的,因为它们是编号文件。样式表(“wn.xsl”)是程序化创建的,并在创建目录时保存在 WordnetFiles
目录中。或者...
将 XML 查看为 HTML:以下代码将创建一个简单的 Visual Basic 浏览器,其中包含用于查看 XML/HTML 文件的自动完成文本框。XML 文件“WNdicty.xml”在处理 XML 文件期间创建,并将词典保存为键值对,格式为 <p><k></k><v></v></p>
。该文件要到所有文件都保存完毕后才会保存,因此如果您想尝试此功能,必须运行整个子程序。
- 在 VS 2010 中,创建一个新的 Windows 窗体项目,并在 Visual Basic 中将目标框架设置为 3.5。它可能在其他版本中也能工作,但如果不能,您需要自行转换。
- 添加一个文本框,并将其停靠在窗体的顶部。
- 添加一个
WebBrowser
控件,并将Dock
属性设置为“Fill
”,将ScriptErrorSuppressed
属性设置为“true
”。 - 将窗体拉伸到适当的查看尺寸。
- 双击窗体(或按 F7)以显示 Form1。用以下代码替换空的
Form1
。 - 将此项目中创建的“WordnetFiles”文件夹复制到新项目的 debug 文件夹中。
此代码不带注释,没有解释,旨在提供一个基本的查看器,用于查找文件,或学习 XSL 样式表(别问我 - 在我发现 CodeProject 之前我读的是《XML for Dummies》),或者如果您愿意,可以作为构建更好词典的基础。否则,我推荐 Wordley。
Public Class Form1
Public Shared AutoCompleteList As AutoCompleteStringCollection = New AutoCompleteStringCollection
Public Shared WNDicty As IDictionary(Of String, String) = New Dictionary(Of String, String)
Public Shared whereiam As String = My.Computer.FileSystem.CurrentDirectory & "\"
Private Sub autocompletefill()
Dim DictySource As XElement = XElement.Load(whereiam & "\WordnetFiles\WNdicty.xml")
WNDicty.Clear()
For Each kvp In DictySource.<p>
Dim searchkey As String = kvp.<k>.Value
Dim ID As String = kvp.<v>.Value
WNDicty.Add(searchkey, ID)
AutoCompleteList.Add(searchkey)
Next
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
autocompletefill()
Me.TextBox1.Select(0, 1)
TextBox1.AutoCompleteSource = AutoCompleteSource.CustomSource
TextBox1.AutoCompleteCustomSource = AutoCompleteList
TextBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend
WebBrowser1.Navigate(whereiam & "WordnetFiles\032\032088.xml", False)
End Sub
Private Sub TextBox1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
If e.KeyCode = Keys.Enter Then
Dim path As String = ""
If WNDicty.TryGetValue(TextBox1.Text, path) Then
Dim foldername As String = path.Substring(0, 3) & "\"
Dim makeurl As String = "file://"
Dim filelocation As String = makeurl & whereiam & _
"WordnetFiles\" & foldername & path & ".xml"
WebBrowser1.Navigate(filelocation, False)
End If
End If
End Sub
End Class
关于 XSL 样式表:我添加了额外的 title(工具提示)属性,以提供悬停说明、颜色、指向 WordNet 站点的链接等。是的,因为它在 WebBrowser
控件中,它确实会查找链接中的 http 地址。这有点烦人,是故意的,目的是激励人们学习编辑 XSL 或使用 Wordley。
关注点
在本文中,我试图表明做事有对有错,并且在开始时投入时间来弄清楚要做什么,是值得花费的时间。
我提供了一些 XML 文件 string
操作的方法示例。Rightfully()
展示了将 WordNet synset 转换为具有正确例句的 dictionary
条目的 string
操作。Wordley()
展示了进一步的 string
操作以及一种将 XML 转换为与 Wordley 兼容的 .txt 文件的方法。在第二个 HTML()
中,我向您展示了如何将 XML 文档转换为单个 XML 文件,每个文件一个单词,并应用 XSLT 样式表将其转换为 HTML。
HTML()
还展示了一个实际使用 XDocument
的示例。我进行了大量搜索,但找不到多少相关信息。这对于包含将 XML 文档转换为 HTML 的 XSL 样式表的处理指令非常有用。
我试图表明 XML 是一种将数据从一种形式转换为另一种形式的通用方法。
WordNet 项目是 计算语言学 的一部分。我将其用作我正在进行的主要项目的基础,其中 HTML()
子程序是我当前工作模型的一个修改部分。在我完成它之前,它可能会发生很大变化。我研究得越多,发现需要学习的东西就越多,但我还没有找到 计算语言学家 的定义。所以我想提出一个定义:一个应用计算机编程和语言学来构建计算机程序以帮助构建更好词典的人。你知道,不仅仅是试图解读语言学家的需求的技术人员,而是真正从两端进行学习和应用。感谢普林斯顿大学的 Wordnet 项目!
这是我为 CodeProject 写的单篇文章,但我希望它成为我的第一篇文章。如果我得到积极的反馈,也许我可以把它展示给人事总监,以支持我关于我在 IT 部门比在维护部门更有价值的说法……
历史
- 2012年11月5日:发布
- 2012年11月19日:文章中的小错别字和澄清;修复了样式表中偶尔会显示错误词性的点