Мне нужно скопировать узел (Set_Item/ForwarderReferenceNumber) в случае многократного повтора, а затем удалить узел «Set_Item», из которого мы взяли значение.
Чтобы найти тот же Set_Item (но другой ForwarderReferenceNumer), нам нужно использовать «Set_Item/GTIN»). -> Итак, в моем примере мы видим, что «GTIN» «LineNum» 2 и 7 идентичен (555), и теперь нам нужно скопировать «Set_Item/ForwarderReferenceNumber» из строки 7 ниже «Set_Item/ForwarderReferenceNumber» строки. 2, а затем удалите весь узел «Set_Item» с помощью «LineNum» 7.
пример XML:
<OSTRPT>
<LineInformation>
<Set_Item>
<LineNum>2</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>666</ForwarderReferenceNumber>
<Date>2</Date>
</Set_Item>
<Set_Item>
<LineNum>7</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>777</ForwarderReferenceNumber>
<Date>3</Date>
</Set_Item>
</LineInformation>
</OSTRPT>Это должен быть правильный вывод:
<OSTRPT>
<LineInformation>
<Set_Item>
<LineNum>2</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>666</ForwarderReferenceNumber>
<ForwarderReferenceNumber>777</ForwarderReferenceNumber>
<Date>2</Date>
</Set_Item>
</LineInformation>
</OSTRPT>Вот мой текущий xslt. (Но решения для этого случая нет)
<xsl:stylesheet version = "1.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:exsl = "http://exslt.org/common" extension-element-prefixes = "exsl">
<xsl:output method = "xml" indent = "yes" encoding = "UTF-8"/>
<xsl:strip-space elements = "*" />
<xsl:template match = "/">
<xsl:choose>
<xsl:when test = "//LineInformation[not(Item)] and //LineInformation[not(Set_Item)]"></xsl:when>
<xsl:when test = "not(//Set_Item) and not(//Item)"></xsl:when>
<xsl:otherwise> <xsl:apply-templates select = "@* | node()"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:key name = "header_text" match = "HeaderText" use = "Text"/>
<xsl:key name = "line_text" match = "LineText" use = "concat(../LineNum, '|', Text)"/>
<xsl:key name = "allowance_charge_header" match = "AllowanceOrCharge_Header" use = "concat(Code, '|', Amount)"/>
<xsl:key name = "allowance_charge_line" match = "AllowanceOrCharge_Line" use = "concat(../LineNum, '|', Code, '|', Amount)"/>
<xsl:key name = "packing_slip" match = "ItemDeliveryInformation" use = "concat(../LineNum, '|', PackingSlipId, '|', DeliveryDate, '|', DeliveredQuantity)"/>
<xsl:key name = "item" match = "Item" use = "concat(LineNum, '|', GTIN, '|', SupplierArticleNumber, '|', Quantity)"/>
<xsl:key name = "set_item" match = "Set_Item" use = "concat(LineNum, '|', GTIN, '|', SupplierArticleNumber, '|', ForwarderReferenceNumber)"/>
<xsl:key name = "WeightAndVolume" match = "WeightAndVolume" use = "Weight_RecId"/>
<xsl:key name = "ContainerInformation" match = "ContainerInformation" use = "SSCC_RecId"/>
<xsl:key name = "ContainerInformation_Set_Item" match = "ContainerInformation_Set_Item" use = "SSCC"/>
<!-- Identity-Template für die nicht explizit benannten Elemente -->
<xsl:template match = "@* | node()">
<xsl:copy>
<xsl:apply-templates select = "@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match = "//Forwarder/Code[//Forwarder/Country = 'DE' and //Forwarder/Name[contains(., 'GLS')]]">
<Code>5</Code>
</xsl:template>
<!-- Entfernt alles nach und inkl. "_" -->
<xsl:template match = "GLN[contains(., '_')]">
<GLN><xsl:value-of select = "substring-before(., '_')"/></GLN>
</xsl:template>
<!-- Entfernt alles nach und inkl. "_" -->
<xsl:template match = "Recipient[contains(., '_')]">
<Recipient><xsl:value-of select = "substring-before(., '_')"/></Recipient>
</xsl:template>
<xsl:template match = "ItemDeliveryInformation_Set_Item">
<xsl:element name = "ItemDeliveryInformation">
<!--copy all other nodes-->
<xsl:apply-templates select = "@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match = "Set_Item">
<xsl:element name = "Item">
<!--copy all other nodes-->
<xsl:apply-templates select = "@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match = "RFF_Line_Set_Item">
<xsl:element name = "RFF_Line">
<!--copy all other nodes-->
<xsl:apply-templates select = "@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match = "ContainerInformation_Set_Item">
<xsl:element name = "ContainerInformation">
<!--copy all other nodes-->
<xsl:apply-templates select = "@* | node()"/>
</xsl:element>
</xsl:template>
<!-- Differenz zwischen bestellter und gelieferter Menge -->
<xsl:template match = "Item/ItemDeliveryInformation[. != '']">
<xsl:copy>
<!--copy all other nodes-->
<xsl:apply-templates select = "@* | node()"/>
<QtyDifference>
<xsl:value-of select = "format-number((./DeliveredQuantity - ../Ordered), '#0.00')"/>
</QtyDifference>
</xsl:copy>
</xsl:template>
<!-- das aufzurufende Template: OrderResponseReference Teil 1-->
<xsl:template name = "last-substring-after">
<xsl:param name = "search"/>
<xsl:param name = "string"/>
<xsl:variable name = "result" select = "substring-after($string, $search)"/>
<xsl:choose>
<xsl:when test = "contains($result, $search)">
<xsl:call-template name = "last-substring-after">
<xsl:with-param name = "search" select = "$search"/>
<xsl:with-param name = "string" select = "$result"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select = "$result"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- das aufzurufende Template: OrderResponseReference Teil 2-->
<xsl:template match = "OrderResponseReference[contains (., '/')]">
<OrderResponseReference>
<xsl:call-template name = "last-substring-after">
<xsl:with-param name = "search" select = "'/'"/>
<xsl:with-param name = "string" select = "."/>
</xsl:call-template>
</OrderResponseReference>
</xsl:template>
<xsl:template match = "OrderResponseReference[not(contains (., '/'))]">
<OrderResponseReference><xsl:value-of select = "." /></OrderResponseReference>
</xsl:template>
<xsl:template match = "HeaderText[generate-id() != generate-id(key('header_text', Text)[1])]" />
<xsl:template match = "LineText[generate-id() != generate-id(key('line_text', concat(../LineNum, '|', Text))[1])]" />
<xsl:template match = "AllowanceOrCharge_Header[generate-id() != generate-id(key('allowance_charge_header', concat(Code, '|', Amount))[1])]" />
<xsl:template match = "AllowanceOrCharge_Line[generate-id() != generate-id(key('allowance_charge_line', concat(../LineNum, '|', Code, '|', Amount))[1])]" />
<xsl:template match = "ItemDeliveryInformation[generate-id() != generate-id(key('packing_slip', concat(../LineNum, '|', PackingSlipId, '|', DeliveryDate, '|', DeliveredQuantity))[1])]" />
<xsl:template match = "Item[generate-id() != generate-id(key('item', concat(LineNum, '|', GTIN, '|', SupplierArticleNumber, '|', Quantity))[1])]" />
<xsl:template match = "Set_Item[generate-id() != generate-id(key('set_item', concat(LineNum, '|', GTIN, '|', SupplierArticleNumber, '|', ForwarderReferenceNumber))[1])]" />
<xsl:template match = "WeightAndVolume[generate-id() != generate-id(key('WeightAndVolume', Weight_RecId)[1])]" />
<xsl:template match = "ContainerInformation[generate-id() != generate-id(key('ContainerInformation', SSCC_RecId)[1])]" />
<xsl:template match = "ContainerInformation_Set_Item[generate-id() != generate-id(key('ContainerInformation_Set_Item', SSCC)[1])]" />
<!-- Delete 0 at PackagingQty -->
<xsl:template match = "PackagingUnit[PackagingQty = '0.00' or AllowanceOrChargeAmount = '0']"/>
<!-- Delete 0 at ContainerInformation/SSCC_RecId -->
<xsl:template match = "ContainerInformation/SSCC_RecId"/>
<!-- Delete 0 at ContainerInformation/SSCC_RecId -->
<xsl:template match = "ContainerInformation_Set_Item/SSCC_RecId"/>
<!-- Delete 0 at WeightAndVolume/Weight_RecId -->
<xsl:template match = "WeightAndVolume/Weight_RecId"/>
<!-- delete empty nodes -->
<xsl:template match = "node()|@*">
<xsl:copy>
<xsl:apply-templates select = "node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match = "*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']"/>
</xsl:stylesheet>Вот пример с повторяющимися строками:
<?xml version = "1.0" encoding = "utf-8" standalone = "yes"?>
<OSTRPT>
<LineInformation>
<Set_Item>
<LineNum>4</LineNum>
<GTIN>4251431238524</GTIN>
<SupplierArticleNumber>95003G4103VS</SupplierArticleNumber>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<StatusDescription>Ware versendet</StatusDescription>
<StatusChangeDate>2024-04-04T14:47:56</StatusChangeDate>
<ForwarderReferenceNumber>090028350002745490</ForwarderReferenceNumber>
<ReferenceDate>2024-04-04T14:47:56</ReferenceDate>
</Set_Item>
<Set_Item>
<LineNum>4</LineNum>
<GTIN>4251431238524</GTIN>
<SupplierArticleNumber>95003G4103VS</SupplierArticleNumber>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<StatusDescription>Ware versendet</StatusDescription>
<StatusChangeDate>2024-04-04T14:48:06</StatusChangeDate>
<ForwarderReferenceNumber>090028350002745513</ForwarderReferenceNumber>
<ReferenceDate>2024-04-04T14:47:56</ReferenceDate>
</Set_Item>
<Set_Item>
<LineNum>4</LineNum>
<GTIN>4251431238524</GTIN>
<SupplierArticleNumber>95003G4103VS</SupplierArticleNumber>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<StatusDescription>Ware versendet</StatusDescription>
<StatusChangeDate>2024-04-04T14:48:06</StatusChangeDate>
<ForwarderReferenceNumber>090028350002745513</ForwarderReferenceNumber>
<ReferenceDate>2024-04-04T14:47:56</ReferenceDate>
</Set_Item>
</LineInformation>
</OSTRPT>Спасибо!
с наилучшими пожеланиями Джулиан
Я думаю, это тоже может мне помочь. В моем xml я получаю один и тот же Set_Item дважды (если GTIN один и тот же на разных узлах - это означает, что это одна и та же статья). Но мне это нужно только один раз. Но значение разных ForwarderReferenceNumber не идентично в обеих строках, где GTIN идентичен. Вот почему я сначала скопирую его, прежде чем удалять повторяющиеся строки.
Рассмотрите возможность сокращения примера до минимума, необходимого для демонстрации проблемы — см.: минимальный воспроизводимый пример .
сделанный. Я подумал, что лучше добавить еще несколько узлов, вы можете видеть, что могут быть дополнительные сегменты.
Это действительно проблема с группировкой, найдите «мюнхийский метод группировки xslt».
да, но, пожалуйста, мне нужна помощь, чтобы создать его правильно.





Используйте ключ и обрабатывайте все ForwarderReferenceNumbers в «группе», образованной этим ключом:
const xslt = `<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:key name = "group" match = "Set_Item" use = "GTIN"/>
<xsl:template match = "Set_Item[not(generate-id() = generate-id(key('group', GTIN)[1]))]"/>
<xsl:template match = "ForwarderReferenceNumber">
<xsl:copy-of select = ". | key('group', ../GTIN)/ForwarderReferenceNumber"/>
</xsl:template>
<xsl:template match = "@* | node()">
<xsl:copy>
<xsl:apply-templates select = "@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>`;
var domParser = new DOMParser();
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(domParser.parseFromString(xslt, 'application/xml'));
var resultDoc = xsltProcessor.transformToDocument(domParser.parseFromString(document.getElementById('xml').text, 'application/xml'));
console.info(resultDoc);
console.info(new XMLSerializer().serializeToString(resultDoc));<script id = "xml" type = "application/xml">
<OSTRPT>
<LineInformation>
<Set_Item>
<LineNum>2</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>666</ForwarderReferenceNumber>
<Date>2</Date>
</Set_Item>
<Set_Item>
<LineNum>7</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>777</ForwarderReferenceNumber>
<Date>3</Date>
</Set_Item>
</LineInformation>
</OSTRPT>
</script>Если вам также необходимо удалить дубликаты из ForwarderReferenceNumber, используйте второй ключ:
const xslt = `<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:key name = "gtin-group" match = "Set_Item" use = "GTIN"/>
<xsl:key name = "gtin-ref-group" match = "Set_Item" use = "concat(GTIN, '|', ForwarderReferenceNumber)"/>
<xsl:template match = "Set_Item[not(generate-id() = generate-id(key('gtin-group', GTIN)[1]))]"/>
<xsl:template match = "ForwarderReferenceNumber">
<xsl:copy-of select = ". | key('gtin-group', ../GTIN)[generate-id() = generate-id(key('gtin-ref-group', concat(GTIN, '|', ForwarderReferenceNumber))[1])]/ForwarderReferenceNumber"/>
</xsl:template>
<xsl:template match = "@* | node()">
<xsl:copy>
<xsl:apply-templates select = "@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>`;
var domParser = new DOMParser();
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(domParser.parseFromString(xslt, 'application/xml'));
var resultDoc = xsltProcessor.transformToDocument(domParser.parseFromString(document.getElementById('xml').text, 'application/xml'));
//console.info(resultDoc);
console.info(new XMLSerializer().serializeToString(resultDoc));<script id = "xml" type = "application/xml">
<OSTRPT>
<LineInformation>
<Set_Item>
<LineNum>2</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>666</ForwarderReferenceNumber>
<Date>2</Date>
</Set_Item>
<Set_Item>
<LineNum>7</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>777</ForwarderReferenceNumber>
<Date>3</Date>
</Set_Item>
<Set_Item>
<LineNum>7</LineNum>
<GTIN>555</GTIN>
<Quantity>1.00</Quantity>
<MeasureUnit>PCE</MeasureUnit>
<DeliveryDate>2024-03-13</DeliveryDate>
<Status>24</Status>
<ForwarderReferenceNumber>777</ForwarderReferenceNumber>
<Date>3</Date>
</Set_Item>
</LineInformation>
</OSTRPT>
</script>спасибо большое, в целом выглядит хорошо. но если узел «Set_Item» умножается на тот же «ForwarderReferenceNumber» в XML, то я получаю умноженное значение «ForwarderReferenceNumber» с тем же содержимым. Мне нужен контент только один раз. Надеюсь, вы понимаете мой вопрос. Я добавляю пример в свой вопрос выше.
Я не смог уследить за вашим объяснением. Возможно ли, что это проблема с группировкой?