Jump to content

converting record types into a tree


vsciw
 Share

Recommended Posts

Hi.i have a bit of a problem with a file i'm trying to convert into xml. the file has the same format for each node but with different record types and i want to convert them into a tree using this record type. the input file is like this:<record> <type>A</type> <data>...</data></record><record> <type>B</type> <data>...</data></record><record> <type>C</type> <data>...</data></record><record> <type>C</type> <data>...</data></record><record> <type>C</type> <data>...</data></record><record> <type>B</type> <data>...</data></record><record> <type>C</type> <data>...</data></record><record> <type>C</type> <data>...</data></record>and i want the output like this (with obviously the data in the correct node):<A> <B> <C></C> <C></C> <C></C> </B> <B> <C></C> <C></C> </B>i've almost got it working using templates matching <record>, and inside the template check the type=a b or c. when i have a type=a, i apply the same record template but only select nodes where type=b, and similar when i have a type=b apply template selecting nodes where type=c. <xsl:template match="/"> <records> <xsl:apply-templates select="record[1]"/> </records> </xsl:template> <xsl:template match="record"> <xsl:element name="{type}"> <xsl:choose> <xsl:when test ="type='A'"> <xsl:apply-templates select="following-sibling::record_[type=B]"/> </xsl:when> <xsl:when test ="type='B'"> <xsl:apply-templates select="following-sibling::record_[type=C]"/> </xsl:when> </xsl:choose> </xsl:element> </xsl:template>the problem is that on the first type B, i'm getting all 5 type C output, when i only want the 1st 3 that are before the 2nd type B (if that makes sense!)can anyone help me? i though of using position but not sure how - maybe selecting type C where position > current type B and < next type B ????thanks. ian.

Link to comment
Share on other sites

Hi, this uses xslt 2.0

<?xml version="1.0" encoding="UTF-8"?><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" omit-xml-declaration="no" method="xml"></xsl:output>	<xsl:template match="/">		<records>			<A>			<xsl:variable name="root" select="."></xsl:variable>			<xsl:variable name="numberofb" select="count(//record[type='B'])"></xsl:variable>			<xsl:for-each select="1 to $numberofb">				<B>				<xsl:variable name="current" select="."></xsl:variable>				<xsl:choose>					<xsl:when test="$current != $numberofb">						<xsl:for-each							select="for $T1 in ($root//record[type='B'])[$current], $T2 in ($root//record[type='B'])[$current + 1] return ($T1, $root//*[. >> $T1 and . << $T2])">							<xsl:if test="type='C'">								<C></C>							</xsl:if>						</xsl:for-each> 					</xsl:when>					<xsl:when test="$current = $numberofb">						<xsl:for-each							select="for $T1 in ($root//record[type='B'])[$current] return ($T1, $root//*[. >> $T1 ])">							<xsl:if test="type='C'">								<C></C>							</xsl:if>						</xsl:for-each> 					</xsl:when>				</xsl:choose>				</B>			</xsl:for-each>			</A>		</records>	</xsl:template></xsl:stylesheet>

Regards, John Bampton.

Link to comment
Share on other sites

Hi.wasnt sure what was involved in deploying xslt v2, but managed to find this link using v1.0.http://www.webmasterworld.com/xml/3671431.htmi added levels to the input file, and modified the sample to use a level node not attribute and it appears to be working ok.ian.

Hi, this uses xslt 2.0
<?xml version="1.0" encoding="UTF-8"?><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" omit-xml-declaration="no" method="xml"></xsl:output>	<xsl:template match="/">		<records>			<A>			<xsl:variable name="root" select="."></xsl:variable>			<xsl:variable name="numberofb" select="count(//record[type='B'])"></xsl:variable>			<xsl:for-each select="1 to $numberofb">				<B>				<xsl:variable name="current" select="."></xsl:variable>				<xsl:choose>					<xsl:when test="$current != $numberofb">						<xsl:for-each							select="for $T1 in ($root//record[type='B'])[$current], $T2 in ($root//record[type='B'])[$current + 1] return ($T1, $root//*[. >> $T1 and . << $T2])">							<xsl:if test="type='C'">								<C></C>							</xsl:if>						</xsl:for-each> 					</xsl:when>					<xsl:when test="$current = $numberofb">						<xsl:for-each							select="for $T1 in ($root//record[type='B'])[$current] return ($T1, $root//*[. >> $T1 ])">							<xsl:if test="type='C'">								<C></C>							</xsl:if>						</xsl:for-each> 					</xsl:when>				</xsl:choose>				</B>			</xsl:for-each>			</A>		</records>	</xsl:template></xsl:stylesheet>

Regards, John Bampton.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...