I'm trying to create a regex to get a substring in XSL 2.0 and this is the first time i'm working on XSL.
This is the expression that I'm trying to use to get the substring /(GS\.?\d{4}-\d{4}-\d{4})/g.
If I get any other value like GS.4354-4354-4543-5 or GS.4354-4354-4543-556 I want to extract the value that matches my regex.
If I use 'matches' it is just returning true or false, but my expectation is to trim the additional data. Any help is much appreciated.
I've also tried the following
<xsl:analyze-string select="$messageValue"
regex="(GS\.?\d{4}-\d{4}-\d{4})">
<xsl:matching-substring>
<bug><xsl:value-of select="regex-group(1)"/></bug>
</xsl:matching-substring>
</xsl:analyze-string>
whereas my $messageValue = GS.4354-4354-4543-5 and it is giving empty response.
Input - XML
<?xml version="1.0" encoding="UTF-8"?>
<log>
<logentry revision="265">
<author>dre</author>
<date>2015-04-13T02:35:25.246150Z</date>
<msg>GS.4554-0504-2089-4545</msg>
</logentry>
<logentry revision="73283">
<author>john</author>
<date>2015-04-13T14:10:20.987159Z</date>
<msg>GS.4554-0504-2089-2</msg>
</logentry>
<logentry revision="73290">
<author>ron</author>
<date>2015-04-13T14:24:57.475711Z</date>
<msg>GS-S.4554-0504-2089</msg>
</logentry>
</log>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<html>
<body>
<h2>SVN Issues</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">ver</th>
<th style="text-align:left">author</th>
<th style="text-align:left">date</th>
<th style="text-align:left">ticket</th>
</tr>
<xsl:for-each select="log/logentry">
<tr>
<td><xsl:value-of select="#revision"/></td>
<td><xsl:value-of select="author"/></td>
<td><xsl:value-of select="date"/></td>
<td>
<xsl:variable name="messageValue" select="msg"/>
<xsl:analyze-string select="$messageValue"
regex="(GS\.?\d{4}-\d{4}-\d{4})">
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)"/>
</xsl:matching-substring>
</xsl:analyze-string>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Expected Output -
<html>
<body>
<h2>SVN Issues</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">ver</th>
<th style="text-align:left">author</th>
<th style="text-align:left">date</th>
<th style="text-align:left">ticket</th>
</tr>
<tr>
<td>265</td>
<td>dre</td>
<td>2015-04-13T02:35:25.246150Z</td>
<td>GS.4554-0504-2089</td>
</tr>
<tr>
<td>73283</td>
<td>john</td>
<td>2015-04-13T14:10:20.987159Z</td>
<td>GS.4554-0504-2089</td>
</tr>
<tr>
<td>73290</td>
<td>ron</td>
<td>2015-04-13T14:24:57.475711Z</td>
<td>GS-S.4554-0504-2089</td>
</tr>
</table>
</body>
</html>
Solution from Martin is working when I test it in FreeFormatter.com, but for some reason when I deploy it on my cloud that is running linux this doesn't work. It is always returning empty string. Any one had any idea about it ?
The rexeg attribute can take attribute value templates which use {} as delimiters so to use the literally you need to double them
<xsl:analyze-string select="$messageValue"
regex="(GS\.?\d{{4}}-\d{{4}}-\d{{4}})">
<xsl:matching-substring>
<bug><xsl:value-of select="."/></bug>
</xsl:matching-substring>
</xsl:analyze-string>
Related
I've just started learning XML/XSL and I've hit a roadblock in one of my assignments. Tried Googling and searching over here but I can't seem to find a question that has a solution that is basic. so what I am trying is to display rows of bucket-type and room-types associated with it. can somebody please help
<list-inventory list-count="2">
<list list-type="Standard" list-order = "1" count-Types = "3">
<types type="BEN2D"></room>
<types type="BESH2D"></room>
<types type="HNK"></room>
</list>
<list list-type="Deluxe" list-order = "2" count-Types = "3">
<types type="SNK"></room>
<types type="TESTKD"></room>
<types type="TESTKD"></room>
</list>
<list-inventory>
I want table as below
Standard | Deluxe
BEN2D |SNK
BESH2D |TESTKD
HNK |TESTKD
I tried below xsl code but i see all list-type in single column and only 1st is being printing for all list-type:
<xsl:for-each select="/contents/list-inventory/list">
<tr>
<td class="alt-th" style="border:1px solid black">
<xsl:value-of select="#list-type"/>
</td>
</tr>
<tr>
<td style="border:1px solid black">
<xsl:for-each select="/contents/list-inventory/list/types">
<span><xsl:value-of select="#type"/></span>
<xsl:if test="position()!=last()">
<br/>
</xsl:if>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
Can someone help me with xsl:for-each inside a xsl:for-each
It's too bad you did not post your expected result as code. I would assume that you want a separate row for each pair of values. As I stated in the comments, this is far from being trivial.
However, you could make it simpler if you are willing to settle for a single data row, where each cell contains all the values of the corresponding list (your attempt seems to suggest that this is what you actually tried to accomplish).
So, given a well-formed XML input:
XML
<list-inventory list-count="2">
<list list-type="Standard" list-order = "1" count-Types = "3">
<types type="BEN2D"/>
<types type="BESH2D"/>
<types type="HNK"/>
</list>
<list list-type="Deluxe" list-order = "2" count-Types = "3">
<types type="SNK"/>
<types type="TESTKD"/>
<types type="TESTKD"/>
</list>
</list-inventory>
you could do simply:
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:template match="/list-inventory">
<table border="1">
<!-- header -->
<tr>
<xsl:for-each select="list">
<th>
<xsl:value-of select="#list-type"/>
</th>
</xsl:for-each>
</tr>
<!-- body -->
<tr>
<xsl:for-each select="list">
<td>
<xsl:for-each select="types">
<xsl:value-of select="#type"/>
<br/>
</xsl:for-each>
</td>
</xsl:for-each>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
to get:
Result
<?xml version="1.0" encoding="UTF-8"?>
<table border="1">
<tr>
<th>Standard</th>
<th>Deluxe</th>
</tr>
<tr>
<td>BEN2D<br/>BESH2D<br/>HNK<br/>
</td>
<td>SNK<br/>TESTKD<br/>TESTKD<br/>
</td>
</tr>
</table>
which would render as:
I'm not sure how general you want your solution to be (i.e what inputs does it have to handle other than the example shown), but I would do something like:
<xsl:template match="list-inventory">
<xsl:variable name="list2" select="list[2]/types"/>
<xsl:for-each select="list[1]/types">
<xsl:variable name="position" select="position()"/>
<tr>
<td><xsl:value-of select="#type"/></td>
<td><xsl:value-of select="$list2[$position]/#type"/></td>
</tr>
</xsl:for-each>
</xsl:template>
Both the variables here are needed to avoid problems with context: the effect of an XPath expression depends on the context at the time it is evaluated, so you can evaluate a variable to capture information at the time you're in the right context.
Here is some XSL script:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msa="http://www.publictalksoftware.co.uk/msa">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:variable name="DutyHistory" select="document('DutyAssignHistory.XML')"/>
<xsl:template match="/">
<html>
<head>
<title>Test</title>
</head>
<body>
<xsl:for-each select="MeetingWorkBook/Meeting">
<p>
<xsl:value-of select ="Date/#ThisWeek"/>
</p>
<xsl:variable name="Week" select="Date/#ThisWeek"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[#Week=$Week and #Mode='Weekend']/msa:Assignment[#Index='1' and #IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Platform</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[#Week=$Week and #Mode='Weekend']/msa:Assignment[#Index='5' and #IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Left Mike</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[#Week=$Week and #Mode='Weekend']/msa:Assignment[#Index='7' and #IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Right Mike</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[#Week=$Week and #Mode='Weekend']/msa:Assignment[#Index='8' and #IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Public Talk Chairman</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[#Week=$Week and #Mode='Weekend']/msa:Assignment[#Index='4' and #IndexType='Custom']"/>
</td>
</tr>
<tr>
<td>Watchtower Reader</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[#Week=$Week and #Mode='Weekend']/msa:Assignment[#Index='5' and #IndexType='Custom']"/>
</td>
</tr>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
As you can see it is linking in another XML document for reference. Here is one example of that linked in file:
<?xml version="1.0" encoding="utf-8"?>
<DutyAssignmentHistory xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.publictalksoftware.co.uk/msa">
<DutyAssignments>
<DutyAssignmentEntry Date="2018-01-04" Week="W20180101" Template="0" Mode="Midweek">
<Assignment Index="2" IndexType="Fixed">Name 1</Assignment>
<Assignment Index="5" IndexType="Fixed">Name 2</Assignment>
<Assignment Index="7" IndexType="Fixed">Name 3</Assignment>
<Assignment Index="8" IndexType="Fixed">Name 4</Assignment>
<Assignment Index="13" IndexType="Fixed">Name 5</Assignment>
<Assignment Index="14" IndexType="Fixed">Name 6</Assignment>
</DutyAssignmentEntry>
</DutyAssignments>
</DutyAssignmentHistory>
Potentially a user might want to reference the information in the XML and display it however they like but I am wanting to show them the simplest method.
As you can see there are several criteria:
Week (WYYYYMMDD)
Mode (Midweek, Weekend or Weekly)
Template(0 or higher)
The above will filter to the right week of assignments. Then, to identify the actual assignment:
Index (numeric value)
IndexType (Fixed, CustomFixed or Custom)
Can I use templates in any way (perhaps with variables) to simplify the code as it is getting repetative?
You could use a template and pass parameters, or in XSLT 2.0 or higher you could also define a function, which makes it much easier to use and saves some typing. But for what you are currently doing, a variable and some predicate filters seems to be the most simple and easy.
The most simple and easy way would be to bind a variable with the weekend assignments, and then apply your predicate filter to select the one with the #Index and #IndexType:
<xsl:variable name="Week" select="Date/#ThisWeek"/>
<xsl:variable name="weekend-assignments"
select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments
/msa:DutyAssignmentEntry[#Week=$Week and #Mode='Weekend']/msa:Assignment"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of select="$weekend-assignments[#Index='1' and #IndexType='Fixed']"/>
</td>
</tr>
If you make the variable hold an unfiltered set of Assignment elements, you could perform all of the filtering in the predicates:
<xsl:variable name="Week" select="Date/#ThisWeek"/>
<xsl:variable name="assignments"
select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments
/msa:DutyAssignmentEntry/msa:Assignment"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of
select="$assignments[#Index='1' and #IndexType='Fixed']
[..[#Week=$Week and #Mode='Weekend' and #Template='0']]"/>
</td>
</tr>
If you want to consolidate the logic for generating the columns, you could define a template for msa:Assignment:
<xsl:template match="msa:Assignment">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
And then use it like this:
<table>
<tr>
<td>Sound</td>
<xsl:apply-templates select="$weekend-assignments[#Index='1' and #IndexType='Fixed']"/>
If you want to consolidate the logic for generating rows, you could define a template for msa:Assignment and send in a parameter for the first column:
<xsl:template match="msa:Assignment">
<xsl:param name="label"/>
<tr>
<td><xsl:value-of select="$label"/></td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
And then use it like this:
<table>
<xsl:apply-templates select="$weekend-assignments[#Index='1' and #IndexType='Fixed']">
<xsl:with-param name="label" select="'Sound'"/>
</xsl:apply-templates>
Please suggest to get the absolute path of each documents which are collected thru xslt collection.
Posted script is able to give the required absolute path, but I have used two collections (it may take unnecessary memory to store info of all articles twice, one collection for collecting info and other one to collect document-uri()s).
XMLs:
D:/DocumentPath/Project-01/2016/ABC/Test.xml
<article>
<title>First article</title>
<tag1>The tag 1</tag1>
<tag3>The tag 3</tag3>
</article>
D:/DocumentPath/Project-01/2016/DEF/Test.xml
<article>
<title>Second article</title>
<tag2>The tag 2</tag2>
<tag3>The tag 3</tag3>
</article>
and other XMLs....
XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="varDocuments">
<xsl:copy-of select="collection('file:///D:/DocumentPath/Project-01/2016/?select=*.xml;recurse=yes')
[matches(document-uri(.), '2016/([A-z]+)/.*?.xml')]"/>
</xsl:variable>
<xsl:variable name="varDocuments1">
<xsl:copy-of select="collection('file:///D:/DocumentPath/Project-01/2016/?select=*.xml;recurse=yes')
[matches(document-uri(.), '2016/([A-z]+)/.*?.xml')]/document-uri(.)"/>
</xsl:variable>
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="/">
<Table border="1">
<TR><TH>Position</TH><TH>Title</TH><TH>Tag1</TH><TH>Tag2</TH><TH>Tag3</TH><TH>Tag4</TH><TH>Path</TH></TR>
<xsl:for-each select="$varDocuments">
<xsl:for-each select="article">
<TR>
<xsl:variable name="varPos" select="position()"/>
<td><xsl:value-of select="position()"/></td>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="count(descendant::tag1)"/></td>
<td><xsl:value-of select="count(descendant::tag2)"/></td>
<td><xsl:value-of select="count(descendant::tag3)"/></td>
<td><xsl:value-of select="count(descendant::tag4)"/></td>
<td><xsl:value-of select="normalize-space(tokenize($varDocuments1, 'file:/')[position()=$varPos + 1])"/></td>
</TR>
</xsl:for-each>
</xsl:for-each>
</Table>
</xsl:template>
</xsl:stylesheet>
Required result:
<Table border="1">
<TR>
<TH>Position</TH>
<TH>Title</TH>
<TH>Tag1</TH>
<TH>Tag2</TH>
<TH>Tag3</TH>
<TH>Tag4</TH>
<TH>Path</TH>
</TR>
<TR>
<td>1</td>
<td>First article</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>D:/DocumentPath/Project-01/2016/ABC/Test.xml</td>
</TR>
<TR>
<td>2</td>
<td>Second article</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>D:/DocumentPath/Project-01/2016/DEF/Test.xml</td>
</TR>
<TR>
<td>3</td>
<td>Third article</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>2</td>
<td>D:/DocumentPath/Project-01/2016/GHI/Test.xml</td>
</TR>
</Table>
I would first suggest to change
<xsl:variable name="varDocuments">
<xsl:copy-of select="collection('file:///D:/DocumentPath/Project-01/2016/?select=*.xml;recurse=yes')
[matches(document-uri(.), '2016/([A-z]+)/.*?.xml')]"/>
</xsl:variable>
to at least
<xsl:variable name="varDocuments" select="collection('file:///D:/DocumentPath/Project-01/2016/?select=*.xml;recurse=yes')
[matches(document-uri(.), '2016/([A-z]+)/.*?.xml')]"/>
as there does not seem to be a need to pull in the documents with collection and then create an additional copy with copy-of.
With that correction, when you process each document with with <xsl:for-each select="$varDocuments">, you can simply there read out the document-uri(.) now, as you are processing the documents pulled in and not any copy assembled.
I have a Library object that contains a collection of Books... The Library object has properties like Name, Address, Phone... While the Book object has properties like ISDN, Title, Author, and Price.
XML looks something like this...
<Library>
<Name>Metro Library</Name>
<Address>1 Post Rd. Brooklyn, NY 11218</Address>
<Phone>800 976-7070</Phone>
<Books>
<Book>
<ISDN>123456789</ISDN>
<Title>Fishing with Luke</Title>
<Author>Luke Miller</Author>
<Price>18.99</Price>
</Book>
<Book>
<ISDN>234567890</ISDN>
<Title>Hunting with Paul</Title>
<Author>Paul Worthington</Author>
<Price>28.99</Price>
</Book>
...
And more books
...
</Books>
</Library>
I have a template with space for only 10 per page for example. There can be hundreds of books in the list of Books... So I need to limit the number of books and repeat the template every 10 books.
<?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="/">
<html>
<body>
<div>
<table>
<tr>
<td>NAME</td>
<td><xsl:value-of select="/Library/Name"/></td>
</tr>
<tr>
<td>ADDRESS</td>
<td><xsl:value-of select="/Library/Address"/></td>
</tr>
<tr>
<td>PHONE</td>
<td><xsl:value-of select="/Library/Phone"/></td>
</tr>
</table>
<table>
<xsl:for-each select="/Library/Books/Book">
<tr>
<td><xsl:value-of select="position()"/></td>
<td><xsl:value-of select="ISDN"/></td>
<td><xsl:value-of select="Title"/></td>
<td><xsl:value-of select="Author"/></td>
<td><xsl:value-of select="Price"/></td>
</tr>
</xsl:for-each>
</table>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
How can I get the Library information to appear on all repeating pages and add 10 books per page?... First page has Library info with Books 1 thru 10, Second page has Library info with Books 11 thru 20, and so on??
Thanks
For starters, try not to use for-each, apply-templates allows the engine to optimise the order that events are processed.
It appears that you are calling this stylesheet from some other system, so the approach I've taken is to define a pagination param. In the host language, when you call this just change the root parameter. This then allows you to select the require pages in this line here:
Books/Book[($page - 1)*10 < position() and position() <= ($page)*10]
This should do the trick.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="page" select="1"/>
<xsl:template match="/Library">
<html>
<body>
<div>
<table>
<tr>
<td>NAME</td>
<td>
<xsl:value-of select="/Name"/>
</td>
</tr>
<tr>
<td>ADDRESS</td>
<td>
<xsl:value-of select="/Address"/>
</td>
</tr>
<tr>
<td>PHONE</td>
<td>
<xsl:value-of select="/Phone"/>
</td>
</tr>
</table>
<table>
<xsl:apply-templates select="Books/Book[($page - 1)*10 < position() and position() <= ($page)*10]"/>
</table>
</div>
</body>
</html>
</xsl:template>
<xsl:template match="/Book">
<tr>
<td>
<xsl:value-of select="position()"/>
</td>
<td>
<xsl:value-of select="ISDN"/>
</td>
<td>
<xsl:value-of select="Title"/>
</td>
<td>
<xsl:value-of select="Author"/>
</td>
<td>
<xsl:value-of select="Price"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
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.