I'm calling a template:
<table>
<xsl:apply-templates select="data/pics/row"/>
</table>
The template is
<xsl:template match="row">
<tr>
<xsl:for-each select="td">
<td border="0">
<a href="{#referencddePage}">
<img src="{pic/#src}" width="{pic/#width}" height="{pic/#height}"/>
</a>
</td>
</xsl:for-each>
</tr>
</xsl:template>
My XML is:
<?xml version="1.0" encoding="iso-8859-8"?>
<?xml-stylesheet type="text/xsl" href="xslFiles\smallPageBuilder.xsl"?>
<data pageNo="3" referencePage="xxxxxxxxxxxxxxx.xml">
<pics>
<row no="0">
<td col="0">
<pic src="A.jpg" width="150" height="120"></pic>
</td>
</row>
</pics>
</data>
I want the line :a h r e f="{#referencddePage}" to get the input from
the root, :a h r e f= "{#referencddePage}"..., but I'm already in the <td level>.
I want the line :a h r e
f="{#referencddePage}" to get the
input from the root :a h r e f=
"{#referencddePage}"... but I'm
already in the <td level>
In case it is a rule that the #referencePage attribute is always an attribute of the top element, then it can always be accessed as:
/*/#referencePage
Therefore, in your code you'll have:
<a href="{/*/#referencePage}">
I would recommend not to use <xsl:for-each> and to use only and`. In this way the resulting XSLT code is more understandable and can be more easily modified in the future:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="row">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="td">
<td border="0">
<a href="{/*/#referencePage}">
<xsl:apply-templates/>
</a>
</td>
</xsl:template>
<xsl:template match="pic">
<img src="{#src}" width="{#width}" height="{#height}"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document,
<data pageNo="3" referencePage="xxxxxxxxxxxxxxx.xml">
<pics>
<row no="0">
<td col="0">
<pic src="A.jpg" width="150" height="120"></pic>
</td>
</row>
</pics>
</data>
the wanted output is produced:
<tr>
<td border="0">
<a href="xxxxxxxxxxxxxxx.xml">
<img src="A.jpg" width="150" height="120"/>
</a>
</td>
</tr>
See how each template is so very simple. Also, the code is further simplified.
Now, instead of:
<img src="{pic/#src}" width="{pic/#width}" height="{pic/#height}"/>
we have only:
<img src="{#src}" width="{#width}" height="{#height}"/>
Use an XPATH that "jumps" to the top of the document with a leading slash, then walk down the tree:
/data/#referencePage
Applying it to your stylesheet:
<xsl:template match="row">
<tr>
<xsl:for-each select="td">
<td border="0">
<a href="{/data/#referencePage}">
<img src="{pic/#src}" width="{pic/#width}" height="{pic/#height}"/>
</a>
</td>
</xsl:for-each>
</tr>
</xsl:template>
Related
Hi SO,
New to XSLT and have been debugging this code for a while
The current variable is always returning 0
I need to find the sum of all (X) with the same value of (D) through each (Row)
V and W are related, not sure how to "connect" them
Example:
Row (AAA123)[SomeDesc1] = 1.00 +
Row (BBB456)[SomeDesc1] = 3.00
SumOfSomeDesc1 = 4.00
XSLT 1.0 only
XML:
<Root>
<Row>
<ID>AAA123</ID>
<V>
<X>1.00</X>
</V>
<V>
<X>2.00</X>
</V>
<MultipleFieldsInBetween />
<W>
<D>SomeDesc1</D>
</W>
<W>
<D>SomeDesc2</D>
</W>
</Row>
<Row>
<ID>BBB456</ID>
<V>
<X>3.00</X>
</V>
<V>
<X>4.00</X>
</V>
<MultipleFieldsInBetween />
<W>
<D>SomeDesc1</D>
</W>
<W>
<D>SomeDesc2</D>
</W>
</Row>
</Root>
XSLT Sum (Current):
<xsl:variable name="SumOfX" select="sum(//Row[ID/text()=$ID]/V[D/text()
=$Description])" />
I would tackle it as a grouping problem, first identifying unique descriptions, then finding Rows by the description and finally summing up the elements in the same position:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="desc-group" match="Row/W/D" use="."/>
<xsl:variable name="desc-groups" select="//Row/W/D[generate-id() = generate-id(key('desc-group', .)[1])]"/>
<xsl:key name="row-group" match="Row" use="W/D"/>
<xsl:template match="/Root">
<html>
<body>
<table>
<thead>
<tr>
<th>Description</th>
<th>Sum</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="$desc-groups"/>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="Row/W/D">
<tr>
<td>
<xsl:value-of select="."/>
</td>
<td>
<xsl:variable name="pos" select="count(.. | ../preceding-sibling::W)"/>
<xsl:value-of select="sum(key('row-group', .)/V[position() = $pos]/X)"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
Result is
<html>
<body>
<table>
<thead>
<tr>
<th>Description</th>
<th>Sum</th>
</tr>
</thead>
<tbody>
<tr>
<td>SomeDesc1</td>
<td>4</td>
</tr>
<tr>
<td>SomeDesc2</td>
<td>6</td>
</tr>
</tbody>
</table>
</body>
</html>
I am trying to transform the following code into 3 tables:
<bold>Hello</bold>
<bold>world</bold>
<p>Hello world!</p>
<bold>Please</bold>
<bold>help</bold>
<bold>me</bold>
<p>Please help me.</p>
<h1>This community is great<h1>
<bold>Thank</bold>
<bold>you</bold>
<bold>very</bold>
<bold>much</bold>
The final result should look like this:
<table>
<th>NewHeader1<th>
<tr>
<td>Hello</td>
<td>world</td>
</tr>
</table>
<p>Hello world!</p>
<table>
<th>NewHeader2<th>
<tr>
<td>Please</td>
<td>help</td>
<td>me</td>
</tr>
</table>
<p>Please help me.</p>
<h1>This community is great.<h1>
<table>
<th>NewHeader3<th>
<tr>
<td>Thank</td>
<td>you</td>
<td>very</td>
<td>much</td>
</tr>
</table>
Unfortunately, I achieve only to put all the bold-elements in a single table. Thanks for your help!
Given a well-formed XML input such as:
XML
<root>
<bold>Hello</bold>
<bold>world</bold>
<p>Hello world!</p>
<bold>Please</bold>
<bold>help</bold>
<bold>me</bold>
<p>Please help me.</p>
<h1>This community is great</h1>
<bold>Thank</bold>
<bold>you</bold>
<bold>very</bold>
<bold>much</bold>
</root>
you could use a technique known as sibling recursion:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="bold">
<table>
<th>
<xsl:text>NewHeader</xsl:text>
<xsl:number count="bold[not(preceding-sibling::*[1][self::bold])]"/>
</th>
<tr>
<xsl:apply-templates select="." mode="cell"/>
</tr>
</table>
</xsl:template>
<xsl:template match="bold" mode="cell">
<td>
<xsl:value-of select="."/>
</td>
<!-- sibling recursion -->
<xsl:apply-templates select="following-sibling::*[1][self::bold]" mode="cell"/>
</xsl:template>
<xsl:template match="bold[preceding-sibling::*[1][self::bold]]"/>
</xsl:stylesheet>
to produce:
Result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<table>
<th>NewHeader1</th>
<tr>
<td>Hello</td>
<td>world</td>
</tr>
</table>
<p>Hello world!</p>
<table>
<th>NewHeader2</th>
<tr>
<td>Please</td>
<td>help</td>
<td>me</td>
</tr>
</table>
<p>Please help me.</p>
<h1>This community is great</h1>
<table>
<th>NewHeader3</th>
<tr>
<td>Thank</td>
<td>you</td>
<td>very</td>
<td>much</td>
</tr>
</table>
</root>
I'm using XSL1.0. My editor/debugger is OxygenXML with Saxon (OxygenXML can't debug with MSXML) and it will deployed to work with a 3rd party app that only uses MSXML. This means I can't use a variable containing a nodeset if I want to be able to debug.
The problem could probably be expressed as how to sequentially number output of the following -
<xsl:for-each select="node1">
<xsl:variable name="current_ID" select="ID">
<xsl:for-each select="sub_node1">
<xsl:value-of select="../ID"/>-<xsl:value-of select="Sub_ID"/>
</xsl:for-each>
</xsl:for-each>
understanding that I cannot simply use this in my scenario:
<xsl:for-each select="node1/sub_node1">
<xsl:value-of select="position()"/>
</xsl:for-each>
Below is a manufactured example that shows the problem I'm trying to solve as part of a much larger XSL/XML combo. I basically need to create manufacturing instructions. All nodes in the XML with the exception of products/versions (by qty) are in the correct order and I cannot change it. I need to generate the same set of sequential numbers from 3 different XSL's. My current context will always be shipments/deliveries/delivery_products (i.e. my XSL has to process the nodes in the seq shown). I need to produce a list of products sorted by version qty and their deliveries. Each row should have a sequential no (1-4) in example below
<shipments>
<product>
<name>Product 1</name>
<prod_id>P1</prod_id>
<version>
<version_id>P1_V1</version_id>
<qty>8800</qty>
</version>
<version>
<version_id>P1_V2</version_id>
<qty>1100</qty>
</version>
<version>
<version_id>P1_V3</version_id>
<qty>100</qty>
</version>
</product>
<product>
<name>Product 2</name>
<prod_id>P2</prod_id>
<version>
<version_id>P2_V1</version_id>
<qty>5000</qty>
</version>
<version>
<version_id>P2_V2</version_id>
<qty>5000</qty>
</version>
<version>
<version_id>P2_V3</version_id>
<qty>2000</qty>
</version>
</product>
<deliveries>
<del_id>1</del_id>
<destination>Miami</destination>
<delivery_products>
<version_id>P1_V1</version_id>
<qty>8000</qty>
</delivery_products>
<delivery_products>
<version_id>P2_V1</version_id>
<qty>5000</qty>
</delivery_products>
</deliveries>
<deliveries>
<del_id>2</del_id>
<destination>New York</destination>
<delivery_products>
<version_id>P1_V1</version_id>
<qty>800</qty>
</delivery_products>
<delivery_products>
<version_id>P2_V2</version_id>
<qty>1000</qty>
</delivery_products>
</deliveries>
Expected output is below. Note seq # starts from 1 and counts up to 4
<table>
<thead>
<tr>
<td class="col_head">
Seq
</td>
<td class="col_head">
Version
</td>
<td class="col_head">
Destination
</td>
<td class="col_head">
Qty
</td>
</tr>
</thead>
<tr>
<td colspan="4" class="rev_heading">Product 1</td>
</tr>
<tr>
<td>1</td>
<td>P1_V1</td>
<td>Miami</td>
<td>8000</td>
</tr>
<tr>
<td>2</td>
<td>P1_V1</td>
<td>New York</td>
<td>800</td>
</tr>
<tr>
<td colspan="4" class="rev_heading">Product 2</td>
</tr>
<tr>
<td>3</td>
<td>P2_V1</td>
<td>Miami</td>
<td>5000</td>
</tr>
<tr>
<td>4</td>
<td>P2_V2</td>
<td>New York</td>
<td>5000</td>
</tr>
</table>
Here's my XSL so far (just stuck a position() in for a place holder for the seq #)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="html" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
<xsl:template match="shipments">
<html>
<head>
<title>Seq Test</title>
<style type="text/css">
table {border: 1px solid black; border-collapse: collapse;}
td {border: 1px solid black; padding: 1px 5px 1px 5px;}
.col_head {font-weight: 600;}
.rev_heading {color: red; text-align: center; padding-top: 15px;}
</style>
</head>
<body>
<table>
<thead>
<tr>
<!-- SEQ# -->
<td class="col_head">
Seq
</td>
<!-- Imprint/Version -->
<td class="col_head">
Version
</td>
<!-- Ship to -->
<td class="col_head">
Destination
</td>
<!-- Qty -->
<td class="col_head">
Qty
</td>
</tr>
</thead>
<xsl:for-each select="product">
<xsl:sort data-type="number" select="qty"/>
<xsl:for-each select="version">
<xsl:variable name="curr_version" select="version_id"/>
<xsl:if test="position() = 1">
<tr>
<td colspan="4" class="rev_heading">
<xsl:value-of select="../name"/>
</td>
</tr>
</xsl:if>
<xsl:for-each select="../../deliveries/delivery_products[version_id = $curr_version]">
<tr >
<!-- SEQ# -->
<td>
<xsl:value-of select="position()"/>
</td>
<!-- Version -->
<td>
<xsl:value-of select="version_id"/>
</td>
<!-- Ship to -->
<td>
<xsl:value-of select="../destination"/>
</td>
<!-- QTY -->
<td>
<xsl:value-of select="qty"/>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I'm using XSL1.0. My editor/debugger is OxygenXML with Saxon
(OxygenXML can't debug with MSXML) and it will deployed to work with a
3rd party app that only uses MSXML. This means I can't use a variable
containing a nodeset if I want to be able to debug.
You can still use oXygen and the EXSLT node-set() function.
When you are finished, simply change the namespace-uri from "http://exslt.org/common" to "urn:schemas-microsoft-com:xslt"
Here is a short example of this technique. Suppose you are finished debugging the below transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates select="num[. mod 3 = 0]"/>
</xsl:variable>
<xsl:copy-of select="sum(ext:node-set($vrtfPass1)/*)"/>
</xsl:template>
<xsl:template match="num">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Then you make the change from the EXSLT namespace-uri to the MSXSL namespace uri:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="urn:schemas-microsoft-com:xslt">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates select="num[. mod 3 = 0]"/>
</xsl:variable>
<xsl:copy-of select="sum(ext:node-set($vrtfPass1)/*)"/>
</xsl:template>
<xsl:template match="num">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Finally, you run this last transformation with MSXML and it produces exactly the same result as the initial transformation that uses EXSLT:
18
Here is a fraction of the XML data I am processing
<?xml version="1.0" encoding="utf-16"?>
<ScorecardSummary>
<DivisionSummary>
<DivisionName>
<string> SYSTEM</string>
</DivisionName>
<ScorecardSummaryByDivision>
<ScorecardSummaryByKPI>
<Header>
<string>Committed Time of Arrival</string>
<string>Goal</string>
<string>1D</string>
<string>7D</string>
<string>QTD</string>
<string>YTD</string>
<string>YTD Event Cars</string>
</Header>
<Data>
<ScorecardContract>
<TypeName>System</TypeName>
<Goal>68</Goal>
<GoalWarning>64.6</GoalWarning>
<TotalCountYear>1234</TotalCountYear>
<Value1D>79</Value1D>
<Value7D>79.2</Value7D>
<ValueQTD>79.1</ValueQTD>
<ValueYTD>73.3</ValueYTD>
</ScorecardContract>
<ScorecardContract>
<TypeName>AG</TypeName>
<Goal>68</Goal>
<GoalWarning>64.6</GoalWarning>
<TotalCountYear>1111</TotalCountYear>
<Value1D>80.9</Value1D>
<Value7D>78.7</Value7D>
<ValueQTD>78.4</ValueQTD>
<ValueYTD>69.7</ValueYTD>
</ScorecardContract>
This is a small part of the XSL that produces the tables:
<xsl:template match="ScorecardSummary/DivisionSummary/DivisionName">
<h1>
<xsl:value-of select="current()/string"/>
</h1>
</xsl:template>
<xsl:template match="ScorecardSummaryByDivision">
<xsl:apply-templates select="current()/ScorecardSummaryByKPI"/>
</xsl:template>
<xsl:template match="ScorecardSummaryByKPI">
<table border="1" cellspacing="0" cellpadding="5">
<tr>
<xsl:choose>
<xsl:when test="count(preceding-sibling::ScorecardSummaryByKPI) mod 6 < 4">
<td>
<table border="1" cellspacing="0" cellpadding="5">
<xsl:apply-templates select="Header"/>
<xsl:apply-templates select="Data"/>
</table>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<table border="1" cellspacing="0" cellpadding="5">
<xsl:apply-templates select="Header"/>
<xsl:apply-templates select="Data"/>
</table>
</td>
</xsl:otherwise>
</xsl:choose>
</tr>
</table>
</xsl:template>
The XSL produces 6 tables repeatedly like this:
1
2
3
4
5
6
1
2
3
4
5
6
But I want to order them like this:
1 4
2 5
3 6
1 4
2 5
3 6
and so on. I tried using this check, but it doesn't work.
count(preceding-sibling::ScorecardSummaryByKPI) mod 6 < 4
Can anyone help?
Explanation
Your table must have two <td> per row (if you want two columns). Your XSLT does generate only one.
Solution is to interate over one half of the list and generate two <td> per iteration.
So first I would define a size of the table. Example:
<xsl:param name="size" select="count(catalog/cd)"/>
Then iterate over only a half of it ($size div 2). The number must be rounded if the input list can contain a non-even number of elements: ceiling($size div 2) (Rounding up to catch last element)
<xsl:for-each select="catalog/cd[ceiling($size div 2) >= position()]">
In each iteration, first render an element itself:
<td><xsl:value-of select="title"/></td>
Then render an appropriate element from the second half of the table (offset is the number defined before: ceiling($size div 2) Half size of the table)
<td><xsl:value-of select="following::cd[ceiling($size div 2)]/title"/></td>
You can wrap element rendering in a separate template to avoid code repeating.
Working example
Check this transformation example with W3C XSL TryIt (http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog):
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:param name="size" select="count(catalog/cd)"/>
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Title</th>
</tr>
<xsl:for-each select="catalog/cd[ceiling($size div 2) >= position()]">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="following::cd[ceiling($size div 2)]/title"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
It splits CD-catalog (given in example link above) in two columns.
Perhaps something like this is what you are looking for:
(This only shows the idea, you have to adapt it to your input.)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/" >
<xsl:apply-templates select="//t[count(preceding-sibling::t) < 3]" mode="tables" />
</xsl:template>
<xsl:template match="t" >
{<xsl:value-of select="text()"/>}
</xsl:template>
<xsl:template match="t" mode="tables">
<table border="1">
<tr>
<td>
<table border="1" >
<xsl:apply-templates select="." />
</table>
</td>
<td>
<table border="1">
<xsl:apply-templates select="following-sibling::t[count(preceding-sibling::t) = count(current()/preceding-sibling::t) +3]" />
</table>
</td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
With this short test input xml:
<?xml version="1.0" encoding="utf-8"?>
<xml>
<tables>
<t>1</t>
<t>2</t>
<t>3</t>
<t>4</t>
<t>5</t>
<t>6</t>
</tables>
</xml>
It will generate this output:
<?xml version="1.0"?>
<table xmlns="http://www.w3.org/1999/xhtml" border="1">
<tr>
<td>
<table border="1">
{1}
</table>
</td>
<td>
<table border="1">
{4}
</table>
</td>
</tr>
</table><table xmlns="http://www.w3.org/1999/xhtml" border="1">
<tr>
<td>
<table border="1">
{2}
</table>
</td>
<td>
<table border="1">
{5}
</table>
</td>
</tr>
</table><table xmlns="http://www.w3.org/1999/xhtml" border="1">
<tr>
<td>
<table border="1">
{3}
</table>
</td>
<td>
<table border="1">
{6}
</table>
</td>
</tr>
</table>
Ok, I'm working through some simple tutorials from here:
http://www.cch.kcl.ac.uk/legacy/teaching/7aavdh06/xslt/html/module_06.html
The first exercise involves creating a transformation that produces a certain output. Unfortunately, although I'm close, I get an unwanted element at the start. i.e.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xhtml"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" />
<xsl:template match="/div/placeName">
<html>
<head />
<body>
<Table>
<tr>
<td>Place Name</td>
<td>
<xsl:value-of select="name" />
</td>
</tr>
<tr>
<td>Place Name (regularised)</td>
<td>
<xsl:value-of select="#reg" />
</td>
</tr>
<tr>
<td>National Grid Reference</td>
<td>
<xsl:value-of select="#key" />
</td>
</tr>
<tr>
<td>Type of building/monument</td>
<td>
<xsl:value-of select="settlement/#type" />
</td>
</tr>
</Table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
but the output I'm getting is:
Location
Place Name Old Warden
Place Name (regularised) Old Warden, St Leonard
National Grid Reference TL 137 443
Type of building/monument Parish church
The rest is fine but the 'Location' is unwanted. The source XML is at the link above. Any idea how I stop the unwanted text appearing? Or, better still, tell me where I'm going wrong! :)
Edit: Here is the output
<?xml version="1.0" encoding="utf-8" ?>
Location
<!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<body>
<table>
<tr>
<td>Place Name</td>
<td>Old Warden</td>
</tr>
<tr>
<td>Place Name (regularised)</td>
<td>Old Warden, St Leonard</td>
</tr>
<tr>
<td>National Grid Reference</td>
<td>TL 137 443</td>
</tr>
<tr>
<td>Type of building/monument</td>
<td>Parish church</td>
</tr>
</table>
</body>
</html>
As Stivel mentions, the "Location" text does come from the head element in your XML.
<div type="location">
<head n="I">Location</head>
<placeName reg="Old Warden, St Leonard" key="TL 137 443">
The reason it is appearing is because of XSTL's built-in templates which it uses when you do not specify a match for an element it is looking for in your XSLT.
You can read up on built-in templates at the W3C page but in short, if XSLT can't find a match it will either continue processing the element's children (without copying the element), or in the case of text or attributes, output the value.
XSLT will start by looking for a match for the document element first, and if you have not provided a template, it will continue looking for a template for the root element, and then its children, and so on.
In your case, you have not provided a template to match anything until /div/placeName, this means XSLT will use the built-in template for the div element. This has two children; head and placeName. You have a template it can use for placeName, but not head and so the built-in template ends up outputing the text for head because you have not told it anything otherwise.
The solution is to simply to add a template to ignore the head element
<xsl:template match="/div/head" />
Here is the full XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xhtml"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" indent="yes" />
<xsl:template match="/div/head" />
<xsl:template match="/div/placeName">
<html>
<head />
<body>
<Table>
<tr>
<td>Place Name</td>
<td>
<xsl:value-of select="name" />
</td>
</tr>
<tr>
<td>Place Name (regularised)</td>
<td>
<xsl:value-of select="#reg" />
</td>
</tr>
<tr>
<td>National Grid Reference</td>
<td>
<xsl:value-of select="#key" />
</td>
</tr>
<tr>
<td>Type of building/monument</td>
<td>
<xsl:value-of select="settlement/#type" />
</td>
</tr>
</Table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
When you use this, this should give the output you need.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xhtml" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
<xsl:template match="div">
<xsl:apply-templates select="placeName"/>
</xsl:template>
<xsl:template match="placeName">
<html>
<head />
<body>
<Table>
<tr>
<td>Place Name</td>
<td>
<xsl:value-of select="name" />
</td>
</tr>
<tr>
<td>Place Name (regularised)</td>
<td>
<xsl:value-of select="#reg" />
</td>
</tr>
<tr>
<td>National Grid Reference</td>
<td>
<xsl:value-of select="#key" />
</td>
</tr>
<tr>
<td>Type of building/monument</td>
<td>
<xsl:value-of select="settlement/#type" />
</td>
</tr>
</Table>
</body>
</html>
</xsl:template>
Probably your <head/> may refer
<head n="I">Location</head>
remove <head/> in xsl and check that.