- РЕДАКТИРОВАТЬ -, уточняющие документы и желаемый результат. (также почему разница между 1-м ответом)
Я пытаюсь сравнить 2 больших XML набора данных с помощью XSLT 2.0 (я также могу использовать 3.0), и у меня возникают проблемы с производительностью.
У меня есть ~ 300 тыс. Записей в файле 1, которые мне нужно сравнить с другими ~ 300 тыс. Записей в файле 2, чтобы увидеть, существуют ли записи из файла 1 в файле 2. Если это так, мне нужно вставить узел в результат. Мне также нужно исключить определенные типы записей из файла 1.
Файл 1
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<col1>100035</col1>
<col2>3000009091</col2>
<col3>SSL</col3>
<col4>8.000000</col4>
<col5>06-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<col1>100002</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>07-Jul-2020</col5>
<col6>P</col6>
</row>
<row>
<col1>100028</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>08-Jul-2020</col5>
<col6>P</col6>
</row>
<row>
<col1>100200</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>09-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<col1>100689</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>10-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<col1>100035</col1>
<col2>3000013528</col2>
<col3>UFH</col3>
<col4>8.000000</col4>
<col5>16-Jul-2020</col5>
<col6>A</col6>
</row>
</root>
Файл 2
<?xml version="1.0" encoding="UTF-8"?>
<nm:Data xmlns:nm="namespace">
<nm:Entry>
<nm:Record>
<nm:ID>10084722-Jun-2020UUT</nm:ID>
</nm:Record>
<nm:Record>
<nm:ID>48548310-Jul-2020SSL</nm:ID>
</nm:Record>
<nm:Record>
<nm:ID>10000201-Jul-2020UUT</nm:ID>
</nm:Record>
<nm:Record>
<nm:ID>57307407-Jul-2020SSL</nm:ID>
</nm:Record>
<nm:Record>
<nm:ID>10003516-Jul-2020UFH</nm:ID>
</nm:Record>
<nm:Record>
<nm:ID>10020009-Jul-2020UUT</nm:ID>
</nm:Record>
<nm:Record>
<nm:ID>00155501-Jun-2020UUT</nm:ID>
</nm:Record>
<nm:Record>
<nm:ID>10533728-May-2020UUT</nm:ID>
</nm:Record>
</nm:Entry>
<nm:Entry>
<nm:Record>
<nm:ID>99954801-Jul-2020UUT</nm:ID>
</nm:Record>
</nm:Entry>
<nm:Entry>
<nm:Record>
<nm:ID>30254801-Jun-2020UFH</nm:ID>
</nm:Record>
</nm:Entry>
</nm:Data>
Желаемый результат (скопируйте записи A и добавить узел "тип"). «Adj», если есть соответствующий идентификатор из файла 2, в противном случае тип «New»:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<type>New</type>
<col1>100035</col1>
<col2>3000009091</col2>
<col3>SSL</col3>
<col4>8.000000</col4>
<col5>06-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<type>Adj</type>
<col1>100200</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>09-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<type>New</type>
<col1>100689</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>10-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<type>Adj</type>
<col1>100035</col1>
<col2>3000013528</col2>
<col3>UFH</col3>
<col4>8.000000</col4>
<col5>16-Jul-2020</col5>
<col6>A</col6>
</row>
</root>
Первоначально я не мог получить точный результат, поэтому я пошел на компромисс с помощью следующего xslt; однако производительность низкая, и мне нужно гораздо более эффективное решение.
Попытка XSLT 1 (требуется заменить функции exists () и copy-of ()):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:nm="namespace"
exclude-result-prefixes="xs" version="3.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="report" select="document('File2.xml')"/>
<xsl:template match="root">
<root>
<xsl:for-each select="row[col6 = 'A']">
<record>
<!-- Create value to match against -->
<xsl:variable name="inputID" select="concat(col1,col5,col3)"/>
<!-- Add Node based on existing match or not -->
<xsl:choose>
<xsl:when test="exists($report/nm:Data/nm:Entry/nm:Record/nm:ID[. = $inputID])">
<type>Adj</type>
</xsl:when>
<xsl:otherwise>
<type>New</type>
</xsl:otherwise>
</xsl:choose>
<!-- Copy all other nodes -->
<xsl:copy-of select="."/>
</record>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Фактический результат 1 (не идеальный результат, но приемлемый):
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:nm="namespace">
<record>
<type>New</type>
<row>
<col1>100035</col1>
<col2>3000009091</col2>
<col3>SSL</col3>
<col4>8.000000</col4>
<col5>06-Jul-2020</col5>
<col6>A</col6>
</row>
</record>
<record>
<type>Adj</type>
<row>
<col1>100200</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>09-Jul-2020</col5>
<col6>A</col6>
</row>
</record>
<record>
<type>New</type>
<row>
<col1>100689</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>10-Jul-2020</col5>
<col6>A</col6>
</row>
</record>
<record>
<type>Adj</type>
<row>
<col1>100035</col1>
<col2>3000013528</col2>
<col3>UFH</col3>
<col4>8.000000</col4>
<col5>16-Jul-2020</col5>
<col6>A</col6>
</row>
</record>
</root>
Затем я воспользовался приведенными ниже предложениями и попытался применить как потоковую передачу, так и функцию key () в XSLT 3.0, но мне не удалось заставить что-либо работать. Самым близким был этот xslt здесь, но вывод неверен.
Попытка XSLT 3.0:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:nm="namespace"
exclude-result-prefixes="#all" version="3.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="report" select="document('File2.xml')"/>
<xsl:key name="ref" match="nm:Data/nm:Entry/nm:Record/nm:ID" use="."/>
<xsl:key name="type-ref" match="row" use="col6"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="key('type-ref', 'A')[key('ref', col1 || col3 || col5, $report)]">
<xsl:copy>
<type>Adj</type>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="key('type-ref', 'A')[not(key('ref', col1 || col3 || col5, $report))]">
<xsl:copy>
<type>New</type>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="key('type-ref', 'P')"/>
</xsl:stylesheet>
Вывод 3.0 (обратите внимание, что тип «Adj» не применяется правильно, но P записывает сбрасываются):
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<type>New</type>
<col1>100035</col1>
<col2>3000009091</col2>
<col3>SSL</col3>
<col4>8.000000</col4>
<col5>06-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<type>New</type>
<col1>100200</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>09-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<type>New</type>
<col1>100689</col1>
<col2>3000009091</col2>
<col3>UUT</col3>
<col4>8.000000</col4>
<col5>10-Jul-2020</col5>
<col6>A</col6>
</row>
<row>
<type>New</type>
<col1>100035</col1>
<col2>3000013528</col2>
<col3>UFH</col3>
<col4>8.000000</col4>
<col5>16-Jul-2020</col5>
<col6>A</col6>
</row>
</root>
У меня недостаточно глубокого понимания функции key (), чтобы настроить ее дальше или как правильно применять операторы copy () при попытке использовать режим потока.
Еще раз спасибо за ввод, и я буду продолжать попытки.