I want to transform xml to html using xsl but I'm struggling to make it work although it should be pretty straightforward.
Input XML:
<EEExport Version="201510" Language="International" LanguageIsoCode="int-INT">
<Navigation>
<Navigation Name="Navigation" NavigationID="E905C889-63EF-431E-BD74-A470685F65E0">
<Navigation Name="Oven" NavigationID="B929861A-57D1-4C20-BE2C-0DC006F4D6CE">
</Navigation>
<Navigation Name="Cooker" NavigationID="643B0A58-D83B-4D8F-9E97-A5C8E572B1E5">
</Navigation>
<Navigation Name="Dishwasher" NavigationID="FAB9B544-109D-4B83-A6E4-25114E1D25BA">
<Product ProductID="887B5B3C-F9C7-4F4A-8E0B-1FC62830C508">
<MasterData>
<Brand>Brand1</Brand>
<ProductCode>911 424 310</ProductCode>
<Category ID="B1679547-77B2">Dish_Washer</Category>
</MasterData>
<Containers>
<Container ContainerName="STechSpec_Dish_Washer">
<Attribute AttributeID="36214A61" Name="ModelD" >F55600IM0P</Attribute>
<Attribute AttributeID="C3C36430" Name="BarCode" >7332543317288</Attribute>
<Attribute AttributeID="0B38C70E" Name="CutleryShelves" >None</Attribute>
</Container>
</Containers>
</Product>
<Product ProductID="D4DB8281-42D7-4240-8731-220FD728481D">
<MasterData>
<Brand>Brand2</Brand>
<ProductCode>911 536 090</ProductCode>
<Category ID="B1679547-77B2">Dish_Washer</Category>
</MasterData>
<Containers>
<Container ContainerName="STechSpec_Dish_Washer">
<Attribute AttributeID="36214A61" Name="ModelD" >ZDT26020FA</Attribute>
<Attribute AttributeID="C3C36430" Name="BarCode" >7332543397303</Attribute>
<Attribute AttributeID="0B38C70E" Name="CutleryShelves" >Cutlery Drawer</Attribute>
</Container>
</Containers>
</Product>
</Navigation>
</Navigation>
</Navigation>
</EEExport>
I only want to show specific product fields of category 'Dishwasher'.
Desired output:
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<tr>
<td>Brand1</td>
<td>911 424 310</td>
<td>F55600IM0P</td>
<td>None</td>
</tr>
<tr>
<td>Brand2</td>
<td>911 536 090</td>
<td>ZDT26020FA</td>
<td>Cutlery Drawer</td>
</tr>
</table>
</body>
</html>
Current xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<xsl:for-each select="/EEExport/Navigation/Navigation/Navigation[#Name='Dishwasher']/Product">
<tr>
<td><xsl:value-of select="/Masterdata/Brand"/></td>
<td><xsl:value-of select="/Masterdata/ProductCode"/></td>
<td><xsl:value-of select="/Containers/Container/Attribute[#Name='ModelD']"/></td>
<td><xsl:value-of select="/Containers/Container/Attribute[#Name='CutleryShelves']"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Obviously I'm doing something wrong. Any help is greatly appreciated.
There are two problems with your XSLT.
Firstly, when you start an XPath expression with / then this represents the top-level document node, and so the search will be relative to that, and not to the node you are currently positioned on.
So instead of doing this:
<xsl:value-of select="/Masterdata/Brand"/>
Do this:
<xsl:value-of select="Masterdata/Brand"/>
Having said that, this leads on to the second issue. XML and XSLT are case sensitive. In your XML you use MasterData, but in your XSLT you refer to Masterdata. So, the expression should actually be like this:
<xsl:value-of select="MasterData/Brand"/>
Try this XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<xsl:for-each select="EEExport/Navigation/Navigation/Navigation[#Name='Dishwasher']/Product">
<tr>
<td><xsl:value-of select="MasterData/Brand"/></td>
<td><xsl:value-of select="MasterData/ProductCode"/></td>
<td><xsl:value-of select="Containers/Container/Attribute[#Name='ModelD']"/></td>
<td><xsl:value-of select="Containers/Container/Attribute[#Name='CutleryShelves']"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Related
I need to perform a cyclical sequence within another public secuanci and get the data of each person and each status, the problem that I have with the code is that it does not iterate the data that I am delivering. I need help in the second for-each when I have empty fields and then I can work with Word content controls
XML file
<?xml version="1.0"?>
<emailList>
<person>
<name>name 1</name>
<email>g#gmail.com</email>
<status>
<active>1</active>
<active>2</active>
<active>3</active>
</status>
</person>
<person>
<name>name 2</name>
<email>n#hotmail.com</email>
<status>
<active>4</active>
<active>5</active>
</status>
</person>
</emailList>
XSL file
<xsl:stylesheet version="1.0">
<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0">
<head>
<title>Email Listing</title>
</head>
<body>
<table>
<tr>
<th>Name</th>
<th>E-mail Address</th>
<th>Status</th>
</tr>
<xsl:for-each select="emailList/person">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="email"/></td>
<td>
<xsl:for-each select="emailList/person/status">
<xsl:value-of select="active"/>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
You inner xsl:for-each will be relative to the outer one, which is selecting person.
Try changing it to this...
<xsl:for-each select="status/active">
<xsl:value-of select="."/>
</xsl:for-each>
Where . selects the current node.
If you wanted to separate the values by commas, you could do this....
<xsl:for-each select="status/active">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
Better still, upgrade to XSLT 2.0 and do away with this xsl:for-each entirely..
<td>
<xsl:value-of select="status/active" separator="," />
</td>
<xsl:template match="/">
<html>
<head>
<title>Email Listing</title>
</head>
<body>
<table>
<tr>
<th>Name</th>
<th>E-mail Address</th>
<th>Status</th>
</tr>
<xsl:for-each select="emailList/person">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="email"/></td>
<td>
<xsl:for-each select="status">
<xsl:value-of select="active"/>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
I need to modify my XSLT code for a different output result. I need to output a table with the sigle, number of students and average.
Here's my XML code :
<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet href="class.xsl" type="text/xsl" ?>
<university>
<student><sname>Charlie Parker</name>
<course sigle="INF8430" note="69" />
<course sigle="INF1030" note="65" />
<course sigle="INF1230" note="73" /></student>
<student><name>Miles Davis</name>
<course sigle="INF8430" note="65" />
<course sigle="INF1030" note="77" />
<course sigle="INF1230" note="83" /></student>
<student><name>John Coltrane</name>
<course sigle="INF9430" note="24" />
<course sigle="INF1030" note="64" />
<course sigle="INF1230" note="56" /></student>
<student><name>Charles Mingus</name>
<course sigle="INF8430" note="34" />
<course sigle="INF1230" note="89" /></student>
</university>
Here's my XSLT Code so far :
<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="*"/>
<xsl:template match="/university">
<html>
<body>
<table border="1">
<tr>
<th>Name</th>
<th>Average</th>
</tr>
<xsl:for-each select="student">
<xsl:sort select="substring-after(name, ' ')"/>
<tr>
<td><xsl:value-of select="name" /></td>
<td><xsl:value-of select="sum(course/#note) div count(course)"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Here's what the output should look like :
Thanks a lot for your help!
Your input document is not well-formed, please be careful when posting questions on Stackoverflow.
The standard approach to identify elements that are unique with respect to their content or one of their attributes is to use a key. The best explanation of this is still on Jeni Tennison's web page.
You could also consider using the round() function if there's too much precision in the average column.
XSLT Stylesheet
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="course-sigle" match="course" use="#sigle"/>
<xsl:template match="/university">
<html>
<body>
<table border="1">
<tr>
<th>Sigle</th>
<th>Number of Students</th>
<th>Average</th>
</tr>
<xsl:for-each select="student/course[count(. | key('course-sigle', #sigle)[1]) = 1]">
<xsl:variable name="count" select="count(key('course-sigle', #sigle))"/>
<tr>
<td>
<xsl:value-of select="#sigle"/>
</td>
<td>
<xsl:value-of select="$count"/>
</td>
<td>
<xsl:value-of select="sum(key('course-sigle', #sigle)/#note) div $count"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
HTML Output
<html>
<body>
<table border="1">
<tr>
<th>Sigle</th>
<th>Number of Students</th>
<th>Average</th>
</tr>
<tr>
<td>INF8430</td>
<td>3</td>
<td>56</td>
</tr>
<tr>
<td>INF1030</td>
<td>3</td>
<td>68.66666666666667</td>
</tr>
<tr>
<td>INF1230</td>
<td>4</td>
<td>75.25</td>
</tr>
<tr>
<td>INF9430</td>
<td>1</td>
<td>24</td>
</tr>
</table>
</body>
</html>
Rendered HTML Output
Including the round function, the output looks like
Besides, if you are in charge of designing this XML document, note that some of the names in it are either incomprehensible ("sigle") or inappropriate given the context ("note"). Proper terms would be "signature" and "grade", or "score".
Input:
<?xml version="1.0" encoding="utf-8" ?>
<Software>
<MS version="5.2.3.1"/>
<Java version="5.1.0.29" />
<Oracle id="A" version="1.0.1.11" />
<SQL id="P" version="1.0.1.11" />
</Software>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<table>
<tr>
<xsl:for-each select="//*[1]">
<xsl:for-each select="#*">
<td>
<xsl:value-of select="name()"/>
</td>
</xsl:for-each>
</xsl:for-each>
</tr>
<xsl:for-each select="//*">
<tr>
<xsl:value-of select="local-name()"/> ::
<xsl:for-each select="#*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Output:
Current output [wrong]:
This script gives output without column name
"id". Some "version" column value added in "id(not visible)" column as
there is no attribute name id in node. eg. MS node has version
attribute only hence output result added version info in "id" column.
Please go through output once, possibly save and check in html for proper understanding.
<table>
<tr>
<td/>
<td>
<td>version</td>
</td>
</tr>
<tr>
<td>Software ::
</td>
</tr>
<tr>
<td>MS ::
<td>5.2.3.1</td></td>
</tr>
<tr>
<td>Java ::
<td>5.1.0.29</td></td>
</tr>
<tr>
<td>Oracle ::
<td>A</td><td>1.0.1.11</td></td>
</tr>
<tr>
<td>SQL ::
<td>P</td><td>1.0.1.11</td></td>
</tr>
</table>
Expected output:
Every attribute as columnname/header and all column
have their own value. NOTE: Attributes MS, JAVA, etc as column Name
should not be hard coded because the number of attributes may change on runtime.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td/>
<td>
id<td>version</td>
</td>
</tr>
<tr>
<td>MS ::</td>
<td>Not exist</td><td>5.2.3.1</td>
</tr>
<tr>
<td>Java ::</td>
<td>Not exist</td><td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle ::</td>
<td>A</td><td>1.0.1.11</td>
</tr>
<tr>
<td>SQL ::</td>
<td>P</td><td>1.0.1.11</td>
</tr>
</table>
</body>
</html>
If you are looking to output one column for each possible attribute name, and not restrict it to just id and version, then (in XSLT 1.0) you could make use of a technique called Muenchian Grouping to get the distinct attribute names.
First define a key to look up the attributes by their name
<xsl:key name="columns" match="#*" use="local-name()" />
Then, to get the distinct ones (or rather, get the first occurrence of each distinct name), you can define a variable like so
<xsl:variable name="columns" select="//#*[generate-id() = generate-id(key('columns', local-name())[1])]" />
Then, to output the column headers, you can just iterate over this variable
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="local-name()" /></td>
</xsl:for-each>
For each row, you would take a similar approach. Assuming you were positioned on a child element, you could first define a variable that contains the attributes of the current element. Then you would iterate over the columns variable again, and output the value of the corresponding attribute for the current element
<xsl:variable name="attributes" select="#*" />
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="$attributes[local-name() = local-name(current())]" /></td>
</xsl:for-each>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:key name="columns" match="#*" use="local-name()" />
<xsl:variable name="columns" select="//#*[generate-id() = generate-id(key('columns', local-name())[1])]" />
<xsl:template match="Software">
<table>
<tr>
<td>Software</td>
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="local-name()" /></td>
</xsl:for-each>
</tr>
<xsl:apply-templates select="*" />
</table>
</xsl:template>
<xsl:template match="Software/*">
<tr>
<td><xsl:value-of select="local-name()" /></td>
<xsl:variable name="attributes" select="#*" />
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="$attributes[local-name() = local-name(current())]" /></td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
This should output the following
<table>
<tr>
<td>Software</td>
<td>id</td>
<td>version</td>
</tr>
<tr>
<td>MS</td>
<td/>
<td>5.2.3.1</td>
</tr>
<tr>
<td>Java</td>
<td/>
<td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle</td>
<td>A</td>
<td>1.0.1.11</td>
</tr>
<tr>
<td>SQL</td>
<td>P</td>
<td>1.0.1.11</td>
</tr>
</table>
Note, for brevity, I have not included code to output "Not exists" in the case where the attribute does not exist. But it should be simple enough to add a check for this. (Just store the value in a variable, and use an xsl:choose)
EDIT: If you want to restrict the attributes to specifically be for Software elements too, try changing the key to this:
<xsl:key name="columns" match="Software/*/#*" use="local-name()" />
Hummm, I have tried to fix the HTML issue and the problem you are facing.
This is a bit mannual, but can achieve your requirement. Here is the XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<table>
<tr>
<td></td>
<td>id</td>
<xsl:for-each select="//*[1]">
<xsl:for-each select="#*">
<td><xsl:value-of select="name()"/></td>
</xsl:for-each>
</xsl:for-each>
</tr>
<xsl:for-each select="//*">
<xsl:if test="position() > 1">
<tr>
<td><xsl:value-of select="local-name()"/> ::</td>
<td>
<xsl:choose>
<xsl:when test="#id"><xsl:value-of select="#id"/></xsl:when>
<xsl:otherwise>Not Exist</xsl:otherwise>
</xsl:choose>
</td>
<td>
<xsl:if test="#version"><xsl:value-of select="#version"/></xsl:if>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Here is the output of it:
<table>
<tr>
<td/>
<td>id</td>
<td>version</td>
</tr>
<tr>
<td>MS ::</td>
<td>Not Exist</td>
<td>5.2.3.1</td>
</tr>
<tr>
<td>Java ::</td>
<td>Not Exist</td>
<td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle ::</td>
<td>A</td>
<td>1.0.1.11</td>
</tr>
<tr>
<td>SQL ::</td>
<td>P</td>
<td>1.0.1.11</td>
</tr>
</table>
I have tested it on http://www.xslfiddle.net/
I'm brand new to markup languages and need to display an HTML table, convert it to XML then display it using XSL looking the same as the HTML. Here's a bit of the HTML table:
<table border="1"
cellpadding="5"
summary="Obesity and other statistics">
<tr>
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<tr>
<td>Mississippi</td>
<td>34.4%</td>
<td>17.8%</td>
<td>$36,919</td>
<td>80.4%</td>
</tr>
4 columns, and several rows with 1 title row. Has a summary (not necessary, can be removed for ease), cell padding and a border. Here's the start of the XML table:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="mg.xsl"?>
<data>
<columns>
<State>State</State>
<Obese_adults>Obese adults</Obese_adults>
<Obese_children_and_adolescents>Obese children and adolescents</Obese_children_and_adolescents>
<Median_Household_Income>Median Household Income</Median_Household_Income>
<H_S_Graduation_rate>H.S Graduation rate</H_S_Graduation_rate>
</columns>
<records>
<record>
<State>Mississippi</State>
<Obese_adults>34.4%</Obese_adults>
<Obese_children_and_adolescents>17.8%</Obese_children_and_adolescents>
<Median_Household_Income>$36,919</Median_Household_Income>
<H_S_Graduation_rate>80.4%</H_S_Graduation_rate>
</record>
That was converted following a guideline which may or may not be any good for what I'm trying to do. Couldn't find any clear explanation on what it all does or how to use it with the xsl either.
Here's what I have of the XSL
<?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>
<h2></h2>
<table border="1">
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<xsl:for-each select="data/records/record">
<tr>
<td><xsl:value-of select="State"/></td>
<td><xsl:value-of select="Obese adults"/></td>
<td><xsl:value-of select="Obese children and adolescents"/></td>
<td><xsl:value-of select="Median Household Income"/></td>
<td><xsl:value-of select="H.S Graduation rate"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
which was again formed following a template I found. I have an idea of what it's doing, but not what it's doing wrong and why it isn't working. I would appreciate some help, especially if I am far off of what is the correct way to go about doing this. Thanks
edit: error I'm getting is "Error loading stylesheet: XPath parse failure: operator expected:" by the way.
You have some small mistakes in ur XSLT here is the edited one of yours;
<?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>
<h2></h2>
<table border="1">
<tr>
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<xsl:for-each select="data/records/record">
<tr>
<td><xsl:value-of select="State"/></td>
<td><xsl:value-of select="Obese_adults"/></td>
<td><xsl:value-of select="Obese_children_and_adolescents"/></td>
<td><xsl:value-of select="Median_Household_Income"/></td>
<td><xsl:value-of select="H_S_Graduation_rate"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
the output of this applied to your XML will be;
<html>
<body>
<h2></h2>
<table border="1">
<tr>
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<tr>
<td>Mississippi</td>
<td>34.4%</td>
<td>17.8%</td>
<td>$36,919</td>
<td>80.4%</td>
</tr>
</table>
</body>
</html>
I need to be able to turn a flat xml data sets into html tables, and I'm having trouble finding syntax examples that will fit my need. I would like to use one stylesheet that can convert similar looking data sets into html tables with variable columns.
this is a part of my XML File :
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/xsl" href="XSLT_StyleSheet.xsl"?> <Services>
<Service WsdlUrl="http://venus.eas.asu.edu/WSRepository/Services/BasicThreeSvc/Service.svc">
<Name>ServiceName</Name>
<Provider></Provider>
<Category>CatName</Category>
<Operations>
<Operaion>
<Name>HelloWorld</Name>
<MsgIn>elloWorldInputMessage</MsgIn>
<MsgOut>HelloWorldOutputMessage</MsgOut>
</Operaion>
<Operaion>
<Name>OP2name</Name>
<MsgIn>InputMessage</MsgIn>
<MsgOut>OutputMessage</MsgOut>
</Operaion>
<Operaion>
<Name>Op3Name</Name>
<MsgIn>InputMessage</MsgIn>
<MsgOut>OutputMessage</MsgOut>
</Operaion>
</Operations>
this how the HTML table must look Like:
If you did not find examples of transforming XML to HTML with XSLT, then you didn't look very hard. That's one of its primary motivations. Anyway, this should get you started:
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|#*"/>
<xsl:template match="/Services">
<html>
<head>
<title>XSLT example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="Service">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Operations">
<table>
<thead>
<tr>
<td>Name</td>
<td>Description</td>
<td>Type</td>
</tr>
</thead>
<tbody>
<xsl:apply-templates/>
</tbody>
</table>
</xsl:template>
<xsl:template match="Operaion"> <!-- [sic] -->
<xsl:variable name="service" select="ancestor::Service"/>
<tr>
<td><xsl:value-of select="$service/Name"/></td>
<td><xsl:value-of select="Name"/></td>
<td><xsl:value-of select="$service/Category"/></td>
</tr>
</xsl:template>
</xsl:transform>
Output on your (corrected) document (it was missing end tags):
<html>
<head>
<title>XSLT example</title>
</head>
<body>
<table>
<thead>
<tr>
<td>Name</td>
<td>Description</td>
<td>Type</td>
</tr>
</thead>
<tbody>
<tr>
<td>ServiceName</td>
<td>HelloWorld</td>
<td>CatName</td>
</tr>
<tr>
<td>ServiceName</td>
<td>OP2name</td>
<td>CatName</td>
</tr>
<tr>
<td>ServiceName</td>
<td>Op3Name</td>
<td>CatName</td>
</tr>
</tbody>
</table>
</body>
</html>