Почему редактирование XML / поиск XPath используют такие нелепые объемы памяти?
У меня есть большой XML-файл (около 37 МБ - это основной XML-файл в документе Word объемом около 350 страниц), который я пытаюсь найти в XPath. Я делаю это "вручную", а не программно, открывая файл в редакторе XML и ища там.
Я пробовал с Xmplify, QXmlEdit, SublimeText с расширением XPath и т. Д., И все они страдают от одной и той же проблемы: просто открытие файла смехотворно медленно и требует огромного количества памяти, а поиск XPath почти невозможен,
В качестве примера я просто попытался открыть файл в Xmplify. Это заняло около трех минут, и при отсутствии других открытых документов использование памяти Xmplify возросло до 1 ГБ.
Затем я попытался выполнить этот запрос XPath (я ищу все отслеживаемые вставки, состоящие из строки en):
//w:ins[w:r/w:t = 'en']
Это дало мне SPOD на некоторое время. После 15 минут работы на 100% CPU, Xmplify теперь использовал 60 ГБ памяти, и моя ОС сообщала мне, что у меня закончилась память приложения, и мне нужно было начинать принудительное завершение работы.
Это кажется мне чрезмерным для одного запроса XPath в одном файле, даже если это довольно большой файл. Другие приложения, которые я пытался использовать, были не столь ужасно плохими, но открытие документа и выполнение любого вида запроса XPath по-прежнему занимали минуты, и их использование памяти исчислялось и в ГБ, так что Xmplify не только неэффективен.
Что является причиной этого? Почему XPath (очевидно) так ресурсоемок? Отличается ли она между операционными системами (моя - macOS Sierra)?
Я спорил, стоит ли публиковать это здесь или в StackOverflow, но, поскольку я специально не делаю это программно, я решил, что это, вероятно, лучшее место. Не стесняйтесь мигрировать, если для этого есть лучший стек.
1 ответ
Одним из основных факторов является то, что ваш XPath начинается с//
поэтому каждый XML-элемент всего документа будет проверен на предмет заданного вами предиката - это то же самое, как если бы вы написали/descendant-or-self::*
. Если бы вы могли сузить круг элементов, которые могут иметь значение, например, предоставив абсолютный XPath, например/w:document/w:body/w:p/w:r/w:t/w:ins[w:r/w:t = 'en']t
это, скорее всего, значительно ускорит ваш поиск. Даже если вы не можете назвать все уровни иерархии, но вам нужноw:*
где-то, скорее всего, все же гораздо быстрее.
К вашему сведению, notepad++ с плагином XML также предлагает ограниченную поддержку XPath, поэтому вы можете попробовать его.
К вашему сведению, если у вас есть доступ к установке inubit (поскольку это корпоративная сервисная шина/движок бизнес-процессов, он лицензируется только такими организациями, как компании, но не частными лицами), ИМХО, стоит попробовать. Вы должны изменить параметры редактора настроек Workbench > максимальный размер файла на 40 МБ, чтобы ваш файл хорошо отображался, а затем загрузить XML-файл в редактор XML и запустить поиск на основе XPath.
К вашему сведению, по моему опыту, Saxon довольно быстр, поэтому, возможно, стоит создать XSLT для поиска. Вы можете вызвать его, например, черезjava.exe -jar saxon-he-10.5.jar -xsl:searchScript.xsl -s:input.xml -o:output.xml
и внутриsearchScript.xsl
предоставить простой XSLT, который будет копировать любой найденный элемент вoutput.xml
и добавьте XPath в результат поиска (если он слишком большой, просто удалитеlocation="{fn:path()}"
), например
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="#all" version="3.0">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:template match="/">
<results>
<xsl:for-each select="//w:ins[w:r/w:t = 'en']">
<result location="{fn:path()}">
<xsl:copy-of select=". "/>
</result>
</xsl:for-each>
</results>
</xsl:template>
</xsl:stylesheet>