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

Questions about XML that are not covered by the other forums should go here.
tanquang
Posts: 7
Joined: Wed Apr 28, 2021 10:41 pm

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

Post 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.
Last edited by tanquang on Thu Jun 17, 2021 7:35 pm, edited 1 time in total.
Radu
Posts: 9051
Joined: Fri Jul 09, 2004 5:18 pm

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

Post 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
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
tanquang
Posts: 7
Joined: Wed Apr 28, 2021 10:41 pm

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

Post 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.
tanquang
Posts: 7
Joined: Wed Apr 28, 2021 10:41 pm

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

Post 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.
tanquang
Posts: 7
Joined: Wed Apr 28, 2021 10:41 pm

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

Post 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.
Post Reply