[xsl] Manipulating elements depending on the existence of sub-elements

Subject: [xsl] Manipulating elements depending on the existence of sub-elements
From: "Adil Ladhani" <dillio@xxxxxxxxx>
Date: Tue, 11 Mar 2008 14:51:50 -0400
Hi All,

I'm relatively new to XML and very new to XSL, and this mailing list's
archive has been very helpful for issues that I've run into thus far
so I'm hoping somebody can provide a little bit of insight for me on
the following:

I'm parsing a text file to XML, formatting it into a tab-delimited
file using XSL and the Saxon transformer, and then loading this tab
delimited file into a SQL Server database. The parsed XML is in the
following simplified format:

<Item>
<Line> Text For Line 1 </Line>
<Line> Text For Line 2 </Line>
<Line>
<UniqueInfo>
<Number> 123 </Number>
<Date> 01/02/03 </Date>
</UniqueInfo>
</Line>
</Item>

<Item>
<Line> Text For Line 1 </Line>
<Line> Text For Line 2 </Line>
<Line> Text For Line 3 </Line>
<Line> Text For Line 4 </Line>
<Line> Text For Line 5 </Line>
<Line> Text For Line 6 </Line>
<Line>
<UniqueInfo>
<Number> 456 </Number>
<Date> 01/02/03 </Date>
</UniqueInfo>
</Line>
</Item>
And so on. There are many "Items" each of which contains one or more
"Line"s and one set of "UniqueInfo". The UniqueInfo element contains
identifying information for the given Item. The data will then be put
into a table with columns for Number, Date, Line Number, and Line. The
XSL I'm using is very short and simple and does the trick (in every
case except for the problematic one below).

The problem is that the parser is splitting the text file based on a
string that seperates "Items", however there are one or two very
specific "Items" that may have the splitting string within its "Lines"
(i.e. if the items are seperated by the string "=======", then for one
specific type of Item, "=======" might appear between Lines 2 and 3),
so in these cases the XML generated will look like the following:

<Item>
<Line> Text For Line 1 </Line>
<Line> Text For Line 2 </Line>
</Item>
<Item>
<Line> Text for Line 3 </Line>
<Line>
<UniqueInfo>
<Number> 789 </Number>
<Date> 01/03/04 </Date>
</UniqueInfo>
</Line>
</Item>

Which means that the tab-delimited file will not have an associated
"UniqueInfo" data for Lines 1 and 2 and these rows will not be able to
be inserted into the table in the database.

So my XSL question is: am I able to check for the existence of a
"UniqueInfo" element within an "Item" element, and if one does not
exist, use the UniqueInfo element that the next "Item" contains? For
the example above, I would like Number 789 and Date 01/03/04 to be
associated with the preceding "Item". Ideally this would be handled by
the parser (since Lines 1 and 2 should really be in the same "Item" as
Line 3 and the UniqueInfo), but unfortunately I don't have its source
code to play with at the moment, so if there's something I could do to
handle this in XSL it would save me some time.


This is the XSL for the simplified example above:

<xsl:template match="/">
	<xsl:for-each select="/n1:Item">
		<xsl:variable name="Item" select="."/>
		<xsl:variable name="UniqueInfo" select="$Item/n1:Line/n1:UniqueInfo"/>
			<xsl:for-each select="$Item/n1:Line">
				<xsl:variable name="count" select="position()"/>
				<xsl:value-of select="$count"/><xsl:value-of select="$delim"/>
				<xsl:value-of select="$UniqueInfo/n1:Date"/>
				<xsl:value-of select="$delim"/><xsl:value-of
select="$UniqueInfo/n1:Number"/>
				<xsl:value-of select="$delim"/><xsl:value-of select="."/>
				<xsl:value-of select="$eol"/>
			</xsl:for-each>
	</xsl:for-each>
</xsl:template>

Sorry for the long-winded post and thanks in advance,

Adil

Current Thread