Связанный .lib-файл связан с .dll
У меня была такая же проблема. Скажем, у меня есть проекты MyProject и TestProject. Я эффективно связал файл lib для MyProject с TestProject. Однако этот файл lib был создан, так как была построена DLL для MyProject. Кроме того, я не содержал исходный код для всех методов в MyProject, но только доступ к точкам входа DLL.
Чтобы решить проблему, я построил MyProject как LIB и связал TestProject с этим .lib-файлом (скопируйте вложенный файл .lib в папку TestProject). Затем я смогу снова создать MyProject как DLL. Он компилируется, поскольку lib, с которым связан TestProject, содержит код для всех методов в классах MyProject.
Я вижу несколько возможных проблем. Прежде всего, это:
@doc = Nokogiri::XML(sympFile)
будет вызывать весь XML-файл в память как некоторую структуру данных libxml2 и, вероятно, будет больше, чем необработанный XML-файл.
Затем вы делаете такие вещи:
@doc.xpath(...).each
Это может быть недостаточно умным для создания перечислителя, который просто поддерживает указатель на внутреннюю форму XML, он может создавать копию всего, когда это создает NodeSet
, который возвращает xpath
. Это даст вам еще одну копию большей части расширенной версии XML. Я не уверен, сколько копий и построений массивов происходит здесь, но есть место для справедливого разряда памяти и процессора, даже если он не копирует дубликаты всего.
Затем вы делаете свою копию того, что вас интересует:
symptomsList.push([signId, name])
и, наконец, итерация по этому массиву:
symptomsList.each do |x|
Symptom.where(:name => x[1], :signid => Integer(x[0])).first_or_create
end
Я обнаружил, что анализаторы SAX работают лучше с большими данными но они более громоздки для работы. Вы можете попытаться создать свой собственный парсер SAX примерно так:
class D < Nokogiri::XML::SAX::Document
def start_element(name, attrs = [ ])
if(name == 'DisorderSign')
@data = { }
elsif(name == 'ClinicalSign')
@key = :sign
@data[@key] = ''
elsif(name == 'SignFreq')
@key = :freq
@data[@key] = ''
elsif(name == 'Name')
@in_name = true
end
end
def characters(str)
@data[@key] += str if(@key && @in_name)
end
def end_element(name, attrs = [ ])
if(name == 'DisorderSign')
# Dump @data into the database here.
@data = nil
elsif(name == 'ClinicalSign')
@key = nil
elsif(name == 'SignFreq')
@key = nil
elsif(name == 'Name')
@in_name = false
end
end
end
Структура должна быть довольно четкой: вы наблюдаете за открытием интересующих вас элементов и выполняете набор бухгалтерии когда делаете, затем кешируйте строки, если вы находитесь внутри элемента, который вас интересует, и, наконец, очистите и обработайте данные по мере закрытия элементов. Вы работаете с базой данных, замените комментарий
# Dump @data into the database here.
.
Эта структура упрощает просмотр элементов <Disorder id="17601">
, чтобы вы могли отслеживать, насколько далеко вы ушли. Таким образом, вы можете остановить и перезапустить импорт с небольшими изменениями в вашем скрипте.
Вероятно, у вас не хватает памяти, потому что symptomsList
становится слишком большим в размере памяти. Почему бы не выполнить SQL в цикле xpath?
require 'nokogiri'
sympFile = File.open("Temp.xml")
@doc = Nokogiri::XML(sympFile)
sympFile.close()
@doc.xpath("////DisorderSign").each do |x|
signId = x.at('ClinicalSign').attribute('id').text()
name = x.at('ClinicalSign').element_children().text()
Symptom.where(:name => name, :signid => signId.to_i).first_or_create
end
Возможно также, что файл слишком велик для обработки буфера. В этом случае вы можете нарезать его на более мелкие временные файлы и обрабатывать их по отдельности.
Вы также можете использовать Nokogiri::XML::Reader
. Это более интенсивный объем памяти, чем Nokogiri::XML::SAX
парсер, но вы можете сохранить структуру XML, e.x.
class NodeHandler < Struct.new(:node)
def process
# Node processing logic
#e.x.
signId = node.at('ClinicalSign').attribute('id').text()
name = node.at('ClinicalSign').element_children().text()
end
end
Nokogiri::XML::Reader(File.open('./test/fixtures/example.xml')).each do |node|
if node.name == 'DisorderSign' && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
NodeHandler.new(
Nokogiri::XML(node.outer_xml).at('./DisorderSign')
).process
end
end
На основании этого blog
SAX Parser определенно то, что вы хотите использовать. Если вы что-то вроде меня и не можете дживить с документацией Nokogiri, есть удивительный камень, названный Saxerator , который делает этот процесс очень легким.
Пример того, что вы пытаются сделать -
require 'saxerator'
parser = Saxerator.parser(Temp.xml)
parser.for_tag(:DisorderSign).each do |sign|
signId = sign[:ClinicalSign][:id]
name = sign[:ClinicalSign][:name]
Symtom(:name => name, :id => signId).create!
end