I wish to perform a sort of an XML document, and have the output be in the same structure as the existing document. The reason for doing this, is I need the resulting document to be transformed into a new document.

My source XML is:

<?xml version="1.0" encoding="UTF-8"?>
<Msg xmlns="http://schemas.namespace.org/myschema/myschame.xsd" schemalocation="http://schemas.namespace.org/myschema/myschema.xsd ../myschema.xsd" schemaversion="5">
	<NumberofRecordsEnclosed>7</NumberofRecordsEnclosed>
	<Record>
		<EventSequenceNumber>3</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>4</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>5</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>6</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>1</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>5678</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>2</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>5678</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>7</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
</Msg>

I need the result of this to be:

<?xml version="1.0" encoding="UTF-8"?>
<Msg xmlns="http://schemas.namespace.org/myschema/myschame.xsd" schemalocation="http://schemas.namespace.org/myschema/myschema.xsd ../myschema.xsd" schemaversion="5">
	<NumberofRecordsEnclosed>7</NumberofRecordsEnclosed>
	<Record>
		<EventSequenceNumber>3</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>4</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>5</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>6</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>7</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>1</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>5678</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>2</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>5678</Number>
			</Id>
		</ReplaceRecord>
	</Record>
</Msg>

The XSL that I currently have is:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pre="http://schemas.namespace.org/myschema/myschame.xsd">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

   <xsl:template match="/">
<Msg>
      <xsl:apply-templates select="pre:Msg">
      </xsl:apply-templates>
</Msg>
   </xsl:template>

   <xsl:template match="pre:Msg">

         
      <xsl:for-each select="pre:Record">

            <xsl:sort select="pre:ReplaceRecord/pre:Id/pre:Number" />
            <xsl:sort select="pre:EventSequenceNumber" data-type="number"/>
         <xsl:copy-of select="." />
      </xsl:for-each>


   </xsl:template>

</xsl:stylesheet>

This is the closest I can get. It sorts my XML, but it ruins my namespace declaration. I need a way to copy the root node. When I put a 'copy-of' tag under that template, it copies the whole tree, not just the one node.

How can I copy the root node properly?

My plan is to then 'include' this xsl in another xsl. I need the sorted xml document so I can then perform the transformation on the sorted document.

The final output that I will eventually need to get is:

<?xml version="1.0" encoding="UTF-8"?>
<Msg xmlns="http://schemas.namespace.org/myschema/myschame.xsd" schemalocation="http://schemas.namespace.org/myschema/myschema.xsd ../myschema.xsd" schemaversion="5">
	<NumberofRecordsEnclosed>7</NumberofRecordsEnclosed>
	<Record>
		<EventSequenceNumber>7</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>1234</Number>
			</Id>
		</ReplaceRecord>
	</Record>
	<Record>
		<EventSequenceNumber>2</EventSequenceNumber>
		<ReplaceRecord>
			<Id>
				<Number>5678</Number>
			</Id>
		</ReplaceRecord>
	</Record>
</Msg>

I want a unique entry (with the highest 'EventSequenceNumber') as the result. I can achieve this if my xml already is sorted by 'Number' and 'EventSequenceNumber'. My problem is that I am having issues feeding the filtering XSL with a sorted XML node.

There may be a better way to acheive my objectives, if so, please let me know. However, at this stage, I can only think of doing the transformation in two stages:
1) sort
2) filter

Assistance is greatly appreciated.

I have resolved this. For anyone interested in knowing the solution, it was rather easy (esspecially for those in the know), it just took me ages to resolve it due to the learning process (I was disappointed that I had no replies though - but there you go).

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pre="http://schemas.namespace.org/myschema/myschame.xsd">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

   <xsl:template match="/">
         <xsl:apply-templates select="pre:Msg" />
   </xsl:template>

   <xsl:template match="pre:Msg">
      <xsl:copy>

         
         <xsl:for-each select="pre:Record">

            <xsl:sort select="pre:ReplaceRecord/pre:Id/pre:Number" />
            <xsl:sort select="pre:EventSequenceNumber" data-type="number"/>
            <xsl:copy-of select="."/>
         </xsl:for-each>

      </xsl:copy>

   </xsl:template>

</xsl:stylesheet>

The key points that I learnt/resolved my issue:

* copy-of -> copies children as well
* copy -> copies only the current node
* required the root node copy in the 'pre:Msg' template, not the '/' template.

Unfortunately the need of a solution does not permit one to spend as much time reading as one requires, but at least I got there in the end.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.