Page 1 of 1

How to insert element id ascending and sort by element value?

Posted: Wed Jun 16, 2021 10:44 pm
by tanquang
Here is the content of my XML file:

Code: Select all

<include>
	<data>
		<name>Cat food (Pet 65)</name>
		<goodsSum>2</goodsSum>
		...
	</data>
	<data>
		<name>Dog food (Pet 65)</name>
		<goodsSum>3</goodsSum>
		...
	</data>
	<data>
		<name>Meat (Normal 70)</name>
		<goodsSum>4</goodsSum>
		...
	</data>
	<data>
		<name>Fish food (Pet 65)</name>
		<goodsSum>3</goodsSum>
		...
	</data>
	<data>
		<name>Vegetable (Normal 70)</name>
		<goodsSum>4</goodsSum>
		...
	</data>
	....
</include>
Now, I want to insert element id ascending, starting from 300. Then sort by element name value.
Desired result:

Code: Select all

<include>
	<data>
		<name>Cat food (Pet 65)</name>
		<goodsSum>2</goodsSum>
		...
	</data>
	<data>
		<name>Dog food (Pet 65)</name>
		<goodsSum>3</goodsSum>
		...
	</data>
	<data>
		<name>Fish food (Pet 65)</name>
		<goodsSum>3</goodsSum>
		...
	</data>
	<data>
		<name>Meat (Normal 70)</name>
		<goodsSum>4</goodsSum>
		...
	</data>
	<data>
		<name>Vegetable (Normal 70)</name>
		<goodsSum>4</goodsSum>
		...
	</data>
	....
</include>
How can I accomplish that?
Thanks.

Re: How to insert element id ascending and sort by element value?

Posted: Thu Jun 17, 2021 8:10 am
by Radu
Hi,

For generic XSLT related questions maybe you can try in the future to ask on stack overflow, to get more people of the XSLT community on board.

An XSLT stylesheet would probably look like this:

Code: Select all

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	exclude-result-prefixes="xs"
	version="2.0">
	
	<xsl:output indent="yes"/>
	
	<!-- Copy everything as it is -->
	<xsl:template match="node() | @*">
		<xsl:copy>
			<xsl:apply-templates select="node() | @*"/>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="include">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:for-each select="data">
				<xsl:sort select="name"/>
				<xsl:copy>
					<xsl:apply-templates select="@*"/>
					<xsl:element name="id">
						<xsl:value-of select="299 + position()"/>
					</xsl:element>
					<xsl:apply-templates select="node()"/>
				</xsl:copy>
			</xsl:for-each>
		</xsl:copy>
	</xsl:template>
	
</xsl:stylesheet>
Regards,
Radu

Re: How to insert element id ascending and sort by element value?

Posted: Thu Jun 17, 2021 7:35 pm
by tanquang
Radu wrote: Thu Jun 17, 2021 8:10 am Hi,

For generic XSLT related questions maybe you can try in the future to ask on stack overflow, to get more people of the XSLT community on board.

An XSLT stylesheet would probably look like this:

Code: Select all

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	exclude-result-prefixes="xs"
	version="2.0">
	
	<xsl:output indent="yes"/>
	
	<!-- Copy everything as it is -->
	<xsl:template match="node() | @*">
		<xsl:copy>
			<xsl:apply-templates select="node() | @*"/>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="include">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:for-each select="data">
				<xsl:sort select="name"/>
				<xsl:copy>
					<xsl:apply-templates select="@*"/>
					<xsl:element name="id">
						<xsl:value-of select="299 + position()"/>
					</xsl:element>
					<xsl:apply-templates select="node()"/>
				</xsl:copy>
			</xsl:for-each>
		</xsl:copy>
	</xsl:template>
	
</xsl:stylesheet>
Regards,
Radu
Hello,
Thanks for your answer, however, I realized it was sorting based on name to: 1, 10, 100, 2, 3,... instead of 1, 2, 3,...,10 ,...100,... For example: Pet 1 -> Pet 10 -> Pet 100 -> Pet 2 instead of Pet 1 -> Pet 2 -> Pet 10 -> Pet 100.
I want it to group them as in the question (I updated). Although adding the id seems to have worked correctly.

Re: How to insert element id ascending and sort by element value?

Posted: Thu Jun 17, 2021 7:44 pm
by tanquang
Radu wrote: Thu Jun 17, 2021 8:10 am Hi,

For generic XSLT related questions maybe you can try in the future to ask on stack overflow, to get more people of the XSLT community on board.

An XSLT stylesheet would probably look like this:

Code: Select all

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	exclude-result-prefixes="xs"
	version="2.0">
	
	<xsl:output indent="yes"/>
	
	<!-- Copy everything as it is -->
	<xsl:template match="node() | @*">
		<xsl:copy>
			<xsl:apply-templates select="node() | @*"/>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="include">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:for-each select="data">
				<xsl:sort select="name"/>
				<xsl:copy>
					<xsl:apply-templates select="@*"/>
					<xsl:element name="id">
						<xsl:value-of select="299 + position()"/>
					</xsl:element>
					<xsl:apply-templates select="node()"/>
				</xsl:copy>
			</xsl:for-each>
		</xsl:copy>
	</xsl:template>
	
</xsl:stylesheet>
Regards,
Radu
UPDATE: I slightly changed your XSL code, I added data-type="number" to xsl:sort select="name". Everything seems to be working normally again.

Re: How to insert element id ascending and sort by element value?

Posted: Thu Jun 17, 2021 8:17 pm
by tanquang
Radu wrote: Thu Jun 17, 2021 8:10 am Hi,

For generic XSLT related questions maybe you can try in the future to ask on stack overflow, to get more people of the XSLT community on board.

An XSLT stylesheet would probably look like this:

Code: Select all

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	exclude-result-prefixes="xs"
	version="2.0">
	
	<xsl:output indent="yes"/>
	
	<!-- Copy everything as it is -->
	<xsl:template match="node() | @*">
		<xsl:copy>
			<xsl:apply-templates select="node() | @*"/>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="include">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:for-each select="data">
				<xsl:sort select="name"/>
				<xsl:copy>
					<xsl:apply-templates select="@*"/>
					<xsl:element name="id">
						<xsl:value-of select="299 + position()"/>
					</xsl:element>
					<xsl:apply-templates select="node()"/>
				</xsl:copy>
			</xsl:for-each>
		</xsl:copy>
	</xsl:template>
	
</xsl:stylesheet>
Regards,
Radu
Update 2: Adding data-type="number" to xsl:sort select="name" only seems to help the output sort in ascending order instead of 1, 10, 100, 2,.. . but it doesn't group tags with the same name as in the question.