I am trying to group-by two conditions in one element, which practically means that machine and parts with same ID (before '-' should be grouped.
Input:
<Document>
<DocumentLine>
<ExternalBatchNo>KEC36770</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36770-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-3</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
</Document>
Expected result:
<Document>
<DocumentLine>
<ExternalBatchNo>KEC36770</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36770-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
</Document>
<Document>
<DocumentLine>
<ExternalBatchNo>KEC36771</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-3</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
</Document>
This is what I tried, but this results in an empty machine ID and so only groups on parts.
<xsl:for-each-group select="Message/Documents/Document/DocumentLine" group-by="substring-before(ExternalBatchNo,'-')">
So I am thinking about using some template where he should pick the ExternalBatchNo when value doesn't contain an '-'. But, how?
If you can use xslt version 2.0, you could use something like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Documents">
<xsl:copy>
<!-- Your `substring-before` will not work on strings without the dash. Try tokenize instead -->
<xsl:for-each-group select="Document/DocumentLine" group-by="tokenize(ExternalBatchNo,'-')[1]">
<Document>
<xsl:copy-of select="current-group()"/>
</Document>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Using this source xml:
<?xml version="1.0" encoding="UTF-8"?>
<Message>
<Documents>
<Document>
<DocumentLine>
<ExternalBatchNo>KEC36770</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36770-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-3</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
</Document>
</Documents>
</Message>
will give this result:
<?xml version="1.0" encoding="UTF-8"?>
<Documents>
<Document>
<DocumentLine>
<ExternalBatchNo>KEC36770</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36770-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
</Document>
<Document>
<DocumentLine>
<ExternalBatchNo>KEC36771</ExternalBatchNo>
<Attribute01>machine</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-2</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
<DocumentLine>
<ExternalBatchNo>KEC36771-3</ExternalBatchNo>
<Attribute01>part</Attribute01>
</DocumentLine>
</Document>
</Documents>