我有大约 100 个 XML 文件,我想将它们转换成另一个结构更好的文件。此示例将其转换为 CSV,但我还有一个变体可以将其转换为更好的 XML。格式与我无关。我看到有很多这样的问题,但我发现这些示例很难适应,因为问题不是样式表不起作用,而是它太慢了。
我的数据文件大小在 4-12 MB 之间。我在这里提供的 XSLT 可以很好地处理小文件。例如,当我将文件剪切为 250 KB 时,样式表可以很好地处理它(尽管这已经花费了大约 30 秒)。当我尝试处理实际更大的数据文件时,它似乎永远无法完成工作——即使是一个文件。我有 Oxygen XML Editor,我一直在使用 Saxon-HE 9.5.1.2 进行转换。
一句话:这仍然很慢。我可以让我的电脑过夜或做些什么。这涉及一个格式错误的数据集,我根本不需要经常重复这种转换。
所以我的问题是:
这个 XSLT 中有什么东西让它工作特别慢吗?其他一些方法会更好吗?
这些是简化的工作示例。实际的数据文件在结构上是相同的,但有更多的节点,我在这个例子中称之为“词”。 type 属性指定了我要查找的节点。它是带有方言词及其规范化版本的语言方言数据。
这是 XML。
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<order>
<slot id="ts1" value="1957"/>
<slot id="ts2" value="1957"/>
<slot id="ts3" value="2389"/>
<slot id="ts4" value="2389"/>
<slot id="ts5" value="2389"/>
<slot id="ts6" value="2389"/>
<slot id="ts7" value="3252"/>
<slot id="ts8" value="3252"/>
<slot id="ts9" value="3252"/>
<slot id="ts10" value="3360"/>
</order>
<words type="original word">
<annotation>
<data id_1="ts1" id_2="ts3">
<text>dialectal_word_1</text>
</data>
</annotation>
<annotation>
<data id_1="ts4" id_2="ts7">
<text>dialectal_word_2</text>
</data>
</annotation>
<annotation>
<data id_1="ts8" id_2="ts10">
<text>,</text>
</data>
</annotation>
</words>
<words type="normalized word">
<annotation>
<data id_1="ts2" id_2="ts5">
<text>normalized_word_1</text>
</data>
</annotation>
<annotation>
<data id_1="ts6" id_2="ts9">
<text>normalized_word_2</text>
</data>
</annotation>
</words>
</xml>
这是 XSLT。它试图做的是挑选在 XML 结构中具有匹配值的对。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" encoding="UTF-8" indent="yes"/>
<xsl:template match="/xml">
<xsl:text>original	normalized
</xsl:text>
<xsl:for-each select="words[@type='original word']/annotation/data">
<xsl:sort select="substring-after(@id_1, 'ts')" data-type="number"/>
<xsl:variable name="origStartTimeId" select="@id_1"/>
<xsl:variable name="origEndTimeId" select="@id_2"/>
<xsl:variable name="origStartTime_VALUE" select="/xml/order/slot[@id=$origStartTimeId]/@value"/>
<xsl:variable name="origEndTime_VALUE" select="/xml/order/slot[@id=$origEndTimeId]/@value"/>
<xsl:value-of select="text"/>
<xsl:text>	</xsl:text>
<xsl:for-each select="/xml/words[@type='normalized word']/annotation/data">
<xsl:variable name="normStartTime" select="@id_1"/>
<xsl:variable name="normEndTime" select="@id_2"/>
<xsl:variable name="normStartTime_VALUE" select="/xml/order/slot[@id=$normStartTime]/@value"/>
<xsl:variable name="normEndTime_VALUE" select="/xml/order/slot[@id=$normEndTime]/@value"/>
<xsl:if test="($normStartTime_VALUE = $origStartTime_VALUE) and ($normEndTime_VALUE = $origEndTime_VALUE)">
<xsl:value-of select="text"/>
</xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
什么是输出就是这样:
original normalized
dialectal_word_1 normalized_word_1
dialectal_word_2 normalized_word_2
,
这对我来说很好。
谢谢!
最佳答案
当前样式表中的双嵌套 for-each 效率低下,并且随着文件大小的增长会变得更糟 - 你有(原始单词数)*(规范化单词数)迭代,本质上是二次复杂度(假设文件中原始单词和规范化单词的数量大致相同)。如果您使用键,您可以做得更好,它通过构建一个查找表来工作,您可以使用该查找表非常快速地找到节点(通常是常数而不是线性时间)。
<!-- I've said version="2.0" to match your stylesheet in the question, but this
code is actually valid XSLT 1.0 as it doesn't use any 2.0-specific features
or functions -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" encoding="UTF-8" indent="yes"/>
<!-- first key to look up slot elements by their id -->
<xsl:key name="slotById" match="slot" use="@id" />
<!-- second key to look up normalized word annotations by the value of their slots -->
<xsl:key name="annotationBySlots" match="words[@type='normalized word']/annotation"
use="concat(key('slotById', data/@id_1)/@value, '|',
key('slotById', data/@id_2)/@value)" />
<xsl:template match="/xml">
<xsl:text>original	normalized
</xsl:text>
<xsl:apply-templates select="words[@type = 'original word']/annotation" />
</xsl:template>
<xsl:template match="annotation">
<xsl:value-of select="data/text" />
<xsl:text>	</xsl:text>
<xsl:value-of select="
key('annotationBySlots',
concat(key('slotById', data/@id_1)/@value, '|',
key('slotById', data/@id_2)/@value)
)/data/text" />
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
这应该以线性时间运行(每个原始单词注释一次“迭代”,加上构建查找表所花费的时间,它再次应该与插槽数加上< em="">规范化单词注释)。
关于xml - XSLT 运行速度太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26177156/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
是否有可能:before_filter:authenticate_user!||:authenticate_admin! 最佳答案 before_filter:do_authenticationdefdo_authenticationauthenticate_user!||authenticate_admin!end 关于ruby-on-rails-before_filter运行多个方法,我们在StackOverflow上找到一个类似的问题: https://
之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m
有没有一种简单的方法可以判断ruby脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免