Мне предоставляется XML, аналогичный следующему, который мне нужно обработать.
<root>
<Header/>
<Customer id="1" date="13/04/2014"/>
<Account id="1" date="14/04/2014"/>
<Account id="1" date="01/06/2015"/>
<Address id="1" date="14/04/2014"/>
<Customer id="2" date="12/08/2015"/>
<Account id="2" date="13/08/2015"/>
<Address id="2" date="13/08/2015"/>
<Address id="2" date="03/09/2015"/>
<Address id="2" date="27/01/2017"/>
<Customer id="3" date="04/10/2015"/>
<Customer id="3" date="01/02/2017"/>
<Account id="3" date="05/10/2015"/>
<Address id="3" date="08/10/2015"/>
<Address id="3" date="03/09/2016"/>
</root>
У всех узлов больше атрибутов, но я их убрал. У каждого элемента есть идентификатор и дата. Если есть повторяющиеся элементы с одинаковым идентификатором, то действительным считается элемент с самой последней датой, а более старый следует игнорировать.
Если старые могут быть удалены одновременно, я хотел бы вывести это примерно так.
<Customers>
<Customer id="1">
<Account/>
<Address/>
</Customer>
<Customer id="2">
<Account/>
<Address/>
</Customer>
<Customer id="3">
<Account/>
<Address/>
</Customer>
</Customers>
Если нет, то можно обработать файл в двух преобразованиях (одно для группировки по идентификатору клиента, и у каждого клиента есть несколько полей учетной записи / адреса, а затем в другом преобразовании удалить старые записи)
Исходный XML содержит около миллиона записей, поэтому производительность является проблемой. Преобразование занимает несколько минут, но больше 15 не работает.
В настоящее время у меня есть следующий XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="nodes-by-id" match="//root/*" use="@id"/>
<xsl:template match="root">
<Customers>
<xsl:for-each select="*[count(. | key('nodes-by-id', @id)[1]) = 1]">
<xsl:variable name="current-grouping-key" select="@id"/>
<xsl:variable name="current-group" select="key('nodes-by-id', $current-grouping-key)"/>
<Customer>
<xsl:attribute name="id">
<xsl:value-of select="$current-grouping-key"/>
</xsl:attribute>
<CustomerElements>
<xsl:for-each select="$current-group/Customer">
<CustomerElement>
<xsl:attribute name="date">
<xsl:value-of select="@date"/>
</xsl:attribute>
</CustomerElement>
</xsl:for-each>
</CustomerElements>
<xsl:apply-templates select="$current-group"/>
</Customer>
</xsl:for-each>
</Customers>
</xsl:template>
</xsl:stylesheet>
В настоящее время он просто пытается сгруппировать все элементы по их идентификатору, а затем вывести все элементы Customer. Получаю следующее:
<Customers>
<Customer id="">
<CustomerElements/>
</Customer>
<Customer id="1">
<CustomerElements/>
</Customer>
<Customer id="2">
<CustomerElements/>
</Customer>
<Customer id="3">
<CustomerElements/>
</Customer>
</Customers>
Я получаю клиента с пустым идентификатором, потому что я не игнорирую строку заголовка. Мой настоящий вопрос: почему переменная $ current-group не содержит никаких элементов?
Также есть советы о том, как игнорировать строку заголовка и отфильтровать записи со старыми датами.
<xsl:copy-of select="$current-group"/>
. Кроме того, чтобы исключить пустой идентификатор, вы можете начать с<xsl:for-each select="Customer[count(. | key('nodes-by-id', @id)[1]) = 1]">
. - Тут сразу две проблемы - предлагаю разделить на несколько вопросов. - person michael.hor257k   schedule 06.06.2017<xsl:copy-of select="$current-group"/>
действительно выводит элементы, так что они там. Как мне получить доступ к отдельным элементам этой переменной?<xsl:copy-of select="$current-group[name() = 'Account']"/>
лучший способ? - person Riverchimp   schedule 06.06.2017<xsl:copy-of select="$current-group/Account'"/>
, но это не послужит вашей цели, если вы хотите сгруппировать и отсортировать их. - person michael.hor257k   schedule 06.06.2017<xsl:copy-of select="$current-group/Account"/>
ничего не возвращает, а<xsl:copy-of select="$current-group[name() = 'Account']"/>
возвращает. - person Riverchimp   schedule 06.06.2017<xsl:copy-of select="$current-group[self::Account]"/>
. - person michael.hor257k   schedule 06.06.2017<xsl:copy-of select="$current-group[self::Account]"/>
работает. Спасибо за вашу помощь. - person Riverchimp   schedule 06.06.2017