Compare a processing instruction and get the file name - xslt

I'm writing an XSLT in which I need to see if a value is in preprocessing instruction. In my XML, the preprocessing looks like below.
<?xpp MAIN;1;1;0;0;69;0;0?>
Sample XML
<root>
<?xpp MAIN;1;0;0;0;73;0;0?>
<preface role="guideline">
<title>title</title>
<section role="group">
<para>data</para>
</section>
<section role="group">
<title>
<?xpp lp;0.5p?>Licences</title>
<itemizedlist mark="bullet">
<listitem>
<para>itemdata</para>
</listitem>
</itemizedlist>
</section>
<section role="group">
<title>
<?xpp lp;0.5p?>Letters to the Editor</title>
<itemizedlist mark="bullet">
<listitem>
<para><?xpp MAIN;1;0;0;0;74;0;0?>item data</para>
</listitem>
</itemizedlist>
</section>
</preface>
</root>
Sample1 XML
<root>
<?xpp MAIN;1;0;0;0;83;0;0?>
<preface role="guideline">
<title>title</title>
<section role="group">
<para>data</para>
</section>
<section role="group">
<title>
<?xpp lp;0.5p?>Licences</title>
<itemizedlist mark="bullet">
<listitem>
<para>itemdata</para>
</listitem>
</itemizedlist>
</section>
<section role="group">
<title>
<?xpp lp;0.5p?>Letters to the Editor</title>
<itemizedlist mark="bullet">
<listitem>
<para><?xpp MAIN;1;0;0;0;84;0;0?>item data</para>
</listitem>
</itemizedlist>
</section>
</preface>
</root>
For the below XML, I need to do the task of going through files and checking for the data. The Above sample XML and Sample1 XML are the files that I've loop through.
<root>
<table frame="none" tabstyle="wrap4">
<tgroup cols="4">
<colspec colnum="1" colname="col1" colwidth="10*"/>
<colspec colnum="2" colname="COLSPEC0" colwidth="10.00*"/>
<colspec colnum="3" colname="col2" colwidth="275*"/>
<colspec colnum="4" colname="col3" colwidth="15*"/>
<tbody>
<row>
<entry colsep="0" rowsep="0">Text1</entry>
<entry colsep="0" rowsep="0"/>
<entry colsep="0" rowsep="0"/>
<entry colsep="0" rowsep="0" align="right">75</entry>
</row>
<row>
<entry colsep="0" rowsep="0">Text2</entry>
<entry colsep="0" rowsep="0"/>
<entry colsep="0" rowsep="0"/>
<entry colsep="0" rowsep="0" align="right">84</entry>
</row>
</tbody>
</tgroup>
</table>
</root>
Here first I'm trying to loop through all the files available, in each file, look for the preprocessing containing MAIN in it and then see if my value is present in that preprocessing instruction. Below is my XSLT block.
<xsl:template match="entry[#align='right']" mode="y">
<xsl:analyze-string select="." regex="([0-9]+)">
<xsl:matching-substring>
<xsl:variable name="prent" select="document(document('file:///C:\Users\userId\Desktop\Proview\AUS Journal\02FEB/title.xml')/entry/file/#name)/*[contains(//root/processing-instruction('xpp')[contains(.,'MAIN')],regex-group(1))]/substring-before(tokenize(document-uri(/), '/')[last()], '.')"/>
<xsl:variable name="cha">
<xsl:value-of select="$prent"/>
</xsl:variable>
<xsl:variable name="size">
<xsl:value-of select="string-length($cha)"/>
</xsl:variable>
<xsl:variable name="conct">
<xsl:value-of select="concat($cha,'/pg_',.)"/>
</xsl:variable>
<a href="{$conct}">
<xsl:value-of select="regex-group(1)"/>
</a>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
When I run this I get the below error.
XSLT 2.0 Debugging Error: Error: file:///C:/Users/userId/Desktop/Proview/AUS%20Journal/02FEB/XSLT/Journal.xsl:674: Wrong occurrence to match required sequence type - Details: - XPTY0004: The supplied sequence ('2' item(s)) has the wrong occurrence to match the sequence type xs:string ('zero or one').
please let me know how can I fix this and get job done.
Thanks

Try whether changing the step
*[contains(//root/processing-instruction('xpp')[contains(.,'MAIN')],regex-group(1))]
to
*[//root/processing-instruction('xpp')[contains(.,'MAIN')][contains(., regex-group(1))]]
fixes the problem.

Related

XSLT distinct value of the ancestor element

This is the input XML:
<?xml version = "1.0"?>
<?xml-stylesheet type = "text/xsl" href = "students.xsl"?>
<book>
<chapter label="Chapter 1">
<para>Text Text<link role="kwd" linkend="Gloss_1">Term 1</link> Text</para>
<para>Text Text Text<link role="kwd" linkend="Gloss_2">Term 2</link></para>
<section>
<title>Key Terms</title>
<itemizedlist mark="none">
<listitem><para><link role="kwd" linkend="Gloss_1">Term 1</link> Def 1</para></listitem>
<listitem><para><link role="kwd" linkend="Gloss_2">Term 2</link> Def 2</para></listitem>
</itemizedlist>
</section>
</chapter>
<chapter label="Chapter 2">
<para>Text Text<link role="kwd" linkend="Gloss_3">Term 3</link> Text</para>
<para>Text Text Text<link role="kwd" linkend="Gloss_1">Term 1</link></para>
<section>
<title>Key Terms</title>
<itemizedlist mark="none">
<listitem><para><link role="kwd" linkend="Gloss_1">Term 1</link> Def 3</para></listitem>
<listitem><para><link role="kwd" linkend="Gloss_3">Term 3</link> Def 1</para></listitem>
</itemizedlist>
</section>
</chapter>
<chapter label="Chapter 3">
<para>Text Text<link role="kwd" linkend="Gloss_4">Term 4</link> Text</para>
<para>Text Text Text<link role="kwd" linkend="Gloss_2">Term 2</link></para>
<para>Text Text Text<link role="kwd" linkend="Gloss_5">Term 5</link></para>
<section>
<title>Key Terms</title>
<itemizedlist mark="none">
<listitem><para><link role="kwd" linkend="Gloss_2">Term 2</link> Def 2</para></listitem>
<listitem><para><link role="kwd" linkend="Gloss_4">Term 4</link> Def 4</para></listitem>
<listitem><para><link role="kwd" linkend="Gloss_5">Term 5</link> Def 5</para></listitem>
</itemizedlist>
</section>
</chapter>
<glossary>
<glossentry xml:id="Gloss_1"><glossterm>Term 1</glossterm><glossdef>Def 1</glossdef></glossentry>
<glossentry xml:id="Gloss_2"><glossterm>Term 2</glossterm><glossdef>Def 2</glossdef></glossentry>
<glossentry xml:id="Gloss_3"><glossterm>Term 3</glossterm><glossdef>Def 3</glossdef></glossentry>
<glossentry xml:id="Gloss_4"><glossterm>Term 4</glossterm><glossdef>Def 4</glossdef></glossentry>
<glossentry xml:id="Gloss_5"><glossterm>Term 5</glossterm><glossdef>Def 5</glossdef></glossentry>
</glossary>
</book>
Output would be:
<?xml version="1.0" encoding="utf-8"?>
<glossary>
<row>
<col1>Chapter 1</col1>
<col1>Chapter 2</col1>
<col2>Term 1</col2>
</row>
<row>
<col1>Chapter 1</col1>
<col1>Chapter 3</col1>
<col2>Term 2</col2>
</row>
<row>
<col1>Chapter 2</col1>
<col2>Term 3</col2>
</row>
<row>
<col1>Chapter 3</col1>
<col2>Term 4</col2>
</row>
<row>
<col1>Chapter 3</col1>
<col2>Term 5</col2>
</row>
</glossary>
My code is:
<xsl:result-document href="out.xml">
<glossary>
<xsl:for-each select="book/glossary/glossentry">
<row>
<xsl:for-each select="key('num', #xml:id)">
<col1>
<xsl:value-of select="ancestor::chapter/#label"/>
</col1>
</xsl:for-each>
<col2><xsl:value-of select="glossterm"/></col2>
</row>
</xsl:for-each>
</glossary>
</xsl:result-document>
The glossary items are listed twice in the book - One at the end of each chapter and a consolidated items at the end. I would like to get the chapter number(s) for each glossary term listed at the end of the book. I tried various things but I am unable to get distinct value of the ancestor element. Can someone please help?
I think you could simply reverse your point-of-view:
<xsl:key name="chapter-by-link" match="chapter" use="descendant::link/#linkend" />
<xsl:template match="/">
<!-- other stuff -->
<glossary>
<xsl:for-each select="book/glossary/glossentry">
<row>
<xsl:for-each select="key('chapter-by-link', #xml:id)">
<col1>
<xsl:value-of select="#label"/>
</col1>
</xsl:for-each>
<col2>
<xsl:value-of select="glossterm"/>
</col2>
</row>
</xsl:for-each>
</glossary>
</xsl:template>
I suppose it suffices to select the ancestor::chapter/#label attributes as duplicates would be eliminated with any step selecting nodes so you would just change
<xsl:for-each select="key('num', #xml:id)">
<col1>
<xsl:value-of select="ancestor::chapter/#label"/>
</col1>
</xsl:for-each>
to
<xsl:for-each select="key('num', #xml:id)/ancestor::chapter/#label">
<col1>
<xsl:value-of select="."/>
</col1>
</xsl:for-each>
or perhaps organize the code into small templates to have cleaner code:
<?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="#all"
version="3.0">
<xsl:output indent="yes"/>
<xsl:key name="ref" match="link[#role = 'kwd']" use="#linkend"/>
<xsl:template match="book">
<glossary>
<xsl:apply-templates select="glossary/glossentry"/>
</glossary>
</xsl:template>
<xsl:template match="glossentry">
<row>
<xsl:apply-templates select="key('ref', #xml:id)/ancestor::chapter/#label"/>
<col2>
<xsl:value-of select="glossterm"/>
</col2>
</row>
</xsl:template>
<xsl:template match="chapter/#label">
<col1>
<xsl:value-of select="."/>
</col1>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jyH9rNv

Determine the position of node using XSLT

Given the following XML:
<data>
<content>
<section link-id="32">
<entry id="9">
<title handle="apples">Apples</title>
</entry>
<entry id="1">
<title handle="oranges">Oranges</title>
</entry>
<entry id="4">
<title handle="pears">Pears</title>
</entry>
</section>
<section link-id="23">
<entry id="59">
<title handle="chevrolet">Chevrolet</title>
</entry>
<entry id="31">
<title handle="toyota">Toyota</title>
</entry>
<entry id="54">
<title handle="bmw">BMW</title>
</entry>
</section>
</content>
</data>
Styled by this XSL:
<xsl:template match="data">
<html>
<body>
<xsl:apply-templates select="content/section" />
</body>
</html>
</xsl:template>
<xsl:template match="content/section">
<ul>
<li>
Title: <xsl:value-of select="entry/title"/>
</li>
<li>
Position: <xsl:value-of select="position()"/>
</li>
</ul>
</xsl:template>
How would I display and integer representing the order (1-6) of the selected entry nodes? The expected values would be 1 and 4. The example shows values of 1 and 2, i.e. the position in the selected node set. What I want is the numeric position in the XML file, not the selection.
I am unclear exactly what you are asking about, as your "1 and 4" and reference to "position in the previous node set" is a bit confusing. But I think you have a couple options.
You can process all entries from the start:
<body>
<ul>
<xsl:apply-templates select="content/section/entry"/>
</ul>
</body>
...
<xsl:template match="entry">
<li>
Title: <xsl:apply-templates select="title"/>
</li>
<li>
Position: <xsl:apply-templates select="position()"/>
</li>
</xsl:template>
Or, if you find you have to process the sections and entries separately, then you'll find yourself inside of an entry with position() not helping. At this point you can use <xsl:number level="any"/>. If you are at a position deep inside of an entry, you can use <xsl:number count="entry" level="any"/>.
You are confusing "position" (an English word that describes what you want) with "position()" (an XPath function that gives you something quite different).
Try
<xsl:for-each select="entry[1]">
<xsl:number level="any" from="content"/>
</xsl:for-each>
It looks as if you are deliberately using the XSLT 1.0 "feature" whereby xsl:value-of applied to a node-set ignores all nodes except the first. If you want your code to be compatible with 2.0 (and understandable to the reader) it's best to make this explicit by writing select="entry[1]/title".

xslt 1.0 - Trying to get nodes for a specific value

I've got an XML file that has many similarly named nodes but attributes within certain nodes are unique. I want to output into an HTML page only the nodes that fall under a certain attribute value.
Here is the xml:
<document>
<component>
<section>
<templateId value="temp_1" />
<entry>
<act>
<code displayName="temp_1:code_1" />
</act>
</entry>
<entry>
<act>
<code displayName="temp_1:code_2" />
</act>
</entry>
<entry>
<act>
<code displayName="temp_1:code_3" />
</act>
</entry>
</section>
<section>
<templateId value="temp_2" />
<entry>
<act>
<code displayName="temp_2:code_1" />
</act>
</entry>
<entry>
<act>
<code displayName="temp_2:code_2" />
</act>
</entry>
</section>
</component>
</document>
From this specific example, I want to only get the displayName value from the section that has the templateId value of temp_2. This is the XSL code that I'm using but it is getting everything, not just the section that I want. i know the first "when" is working because the right header (between the span tags) is displaying properly. It's just the for-each through the entries.
<xsl:tempalte match="/">
<xsl:choose>
<xsl:when test="//templateId/#value='temp_2'">
<div style="margin-bottom: 5px; padding: 5px; border-bottom: 1px solid #000000;">
<span style="font-weight: bold;">Template 2: </span>
<br />
<xsl:choose>
<xsl:when test="count(//section/entry) != 0">
<xsl:for-each select="//section/entry">
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:value-of select="act/code/#displayName" />
</xsl:when>
<xsl:otherwise>
<br/>
<xsl:value-of select="act/code/#displayName" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
No codes to display
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:when>
</xsl:choose>
</xsl:template>
It should display like so:
temp_2:code_1
<br>temp_2:code_2
Any help would be greatly appreciated.
I guess you want to completely restudy XSLT and its philosophy. Don't program it like it was BASIC. The basic pattern, at least for your case, is that an XSLT program is a collection of templates to handle matching elements. Instead of littering your code with if and choose, write templates with the proper matching conditions. Instead of BASIC's FOR I=1 TO 10, use <xsl:apply-templates/> to "iterate" over the children. Here's the basic idea:
<xsl:template match="/">
<html>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="templateId"/> <!-- skip templateID elements by default -->
<xsl:template match="templateId[#value='temp_2']">
<div style="margin-bottom: 5px; padding: 5px; border-bottom: 1px solid #000000;">
<span style="font-weight: bold;">Template 2: </span>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="code">
<xsl:value-of select="#displayName"/>
<xsl:if test="position() != 1"><br/></xsl:if>
</xsl:template>
<xsl:template match="section[count(entry)=0]">
No codes to display
</xsl:template>
Why no template for act elements? Well, by default XSLT will provide you with a template which does a <xsl:apply-templates/>.
Based on your description it sounds like you only want the temp_2 values in your for-each.
That being the case you can just update your select to the following:
<xsl:for-each select="//section[templateId/#value = 'temp_2']/entry">
This says to grab any entry under section that has a templateId with an attribute of value that equals 'temp_2'.

Can a custom XSLT definition handle a SOAP response that returns an Array of Objects when defining an MBO?

I seem to have run into a limitation in SUP regarding its ability to handle a SOAP response containing a list of objects and I am wondering if it would be possible to write a custom XSLT to handle this. I am trying to make a call into Jira via the getProjectsNoSchemes method via SOAP. This method returns an array of RemoteProject objects. Ultimately I would like to be able to treat each node as a row in a table, but unfortunately I don't know enough about XSLT to be able to know if this is possible or not. I also don't know if this is even a viable solution in SUP.
A sample of the SOAP response is below:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:GetProjectsNoSchemesResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://www.webserviceX.NET">
<GetProjectsNoSchemesReturn
soapenc:arrayType="ns2:RemoteProject[2]" xsi:type="soapenc:Array"
xmlns:ns2="http://beans.soap.rpc.jira.atlassian.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<GetProjectsNoSchemesReturn href="#id0" />
<GetProjectsNoSchemesReturn href="#id1" />
</GetProjectsNoSchemesReturn>
</ns1:GetProjectsNoSchemesResponse>
<multiRef id="id0" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns3:RemoteProject" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns3="http://beans.soap.rpc.jira.atlassian.com">
<description xsi:type="xsd:string">Mobile Web Project POC
</description>
<id xsi:type="xsd:string">10034</id>
<issueSecurityScheme xsi:type="ns3:RemoteScheme"
xsi:nil="true" />
<key xsi:type="xsd:string">XLIPOC</key>
<lead xsi:type="xsd:string">benm</lead>
<name xsi:type="xsd:string">Redacted Project</name>
<notificationScheme xsi:type="ns3:RemoteScheme"
xsi:nil="true" />
<permissionScheme xsi:type="ns3:RemotePermissionScheme"
xsi:nil="true" />
<projectUrl xsi:type="xsd:string"></projectUrl>
<url xsi:type="xsd:string">https://redacted.com/browse/REDACTED</url>
</multiRef>
<multiRef id="id1" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns4:RemoteProject" xmlns:ns4="http://beans.soap.rpc.jira.atlassian.com"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<description xsi:type="xsd:string"></description>
<id xsi:type="xsd:string">10017</id>
<issueSecurityScheme xsi:type="ns4:RemoteScheme"
xsi:nil="true" />
<key xsi:type="xsd:string">GIC</key>
<lead xsi:type="xsd:string">gregm</lead>
<name xsi:type="xsd:string">REDACTED</name>
<notificationScheme xsi:type="ns4:RemoteScheme"
xsi:nil="true" />
<permissionScheme xsi:type="ns4:RemotePermissionScheme"
xsi:nil="true" />
<projectUrl xsi:type="xsd:string"></projectUrl>
<url xsi:type="xsd:string">https://redacted.com/browse/REDACTED</url>
</multiRef>
</soapenv:Body>
Yes, it's possible, and relatively easy to do so.
Below is an example XSLT that produces an HTML document with a table row for each <multRef> element.
Each child element of <multiRef> is first rendered as a table header using the name of the element for the heading column, and then each <multiRef> is rendered as rows with columns for each of the child elements:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head></head>
<body>
<table border="1">
<xsl:apply-templates select="*/*/multiRef[1]" mode="header"/>
<xsl:apply-templates select="*/*/multiRef" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="multiRef" mode="header">
<thead>
<tr>
<xsl:apply-templates mode="header"/>
</tr>
</thead>
</xsl:template>
<xsl:template match="multiRef/*" mode="header">
<th>
<xsl:value-of select="local-name()"/>
</th>
</xsl:template>
<xsl:template match="multiRef">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="multiRef/*">
<td>
<xsl:apply-templates/>
</td>
</xsl:template>
</xsl:stylesheet>
When applied to the sample XML provided, it produces the following HTML:
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-16">
</head>
<body>
<table border="1">
<thead>
<tr>
<th>description</th>
<th>id</th>
<th>issueSecurityScheme</th>
<th>key</th>
<th>lead</th>
<th>name</th>
<th>notificationScheme</th>
<th>permissionScheme</th>
<th>projectUrl</th>
<th>url</th>
</tr>
</thead>
<tr>
<td>Mobile Web Project POC
</td>
<td>10034</td>
<td></td>
<td>XLIPOC</td>
<td>benm</td>
<td>Redacted Project</td>
<td></td>
<td></td>
<td></td>
<td>https://redacted.com/browse/REDACTED</td>
</tr>
<tr>
<td></td>
<td>10017</td>
<td></td>
<td>GIC</td>
<td>gregm</td>
<td>REDACTED</td>
<td></td>
<td></td>
<td></td>
<td>https://redacted.com/browse/REDACTED</td>
</tr>
</table>
</body>
</html>
SUP expects the XML in a very specific format so I had to traverse through the multi-refs in the response using the for-each construct:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//ns1:getProjectsNoSchemesResponse">
<data>
<Record>
<Field op_label="id" op_position="1" op_datatype="STRING" op_nullable="true">id</Field>
<Field op_label="name" op_position="2" op_datatype="STRING" op_nullable="true">name</Field>
<Field op_label="description" op_position="3" op_datatype="STRING" op_nullable="true">description</Field>
</Record>
<xsl:for-each select="//ns1:getProjectsNoSchemesResponse/getProjectsNoSchemesReturn/href*">
<Record>
<Field>
<xsl:attribute name="op_label">id</xsl:attribute>
<xsl:attribute name="op_position">1</xsl:attribute>
<xsl:attribute name="op_datatype">STRING</xsl:attribute>
<xsl:attribute name="op_nullable">true</xsl:attribute>
<xsl:value-of select="getProjectNoSchemesReturn/id" />
</Field>
<Field>
<xsl:attribute name="op_label">name</xsl:attribute>
<xsl:attribute name="op_position">2</xsl:attribute>
<xsl:attribute name="op_datatype">STRING</xsl:attribute>
<xsl:attribute name="op_nullable">true</xsl:attribute>
<xsl:value-of select="getProjectNoSchemesReturn/name" />
</Field>
<Field>
<xsl:attribute name="op_label">description</xsl:attribute>
<xsl:attribute name="op_position">3</xsl:attribute>
<xsl:attribute name="op_datatype">STRING</xsl:attribute>
<xsl:attribute name="op_nullable">true</xsl:attribute>
<xsl:value-of select="getProjectNoSchemesReturn/name" />
</Field>
</Record>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>

Problem with XSL 1.0 <xsl:for-each> and <call-template>

Please review my code and give me your advise on this:
XML file: content.xml:
<content>
<page id="page-1">
<!-- ... -->
<block-center>
<block-center-row id="block-center-row-1">
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</block-center-row>
<block-center-row id="block-center-row-2">
<block-center-colunm id="block-center-2-1">
<book>
<title>Book Title1</title>
<author>Book Author1</author>
</book>
<book>
<title>Book Title2</title>
<author>Book Author2</author>
</book>
<book>
<title>Book Title3</title>
<author>Book Author3</author>
</book>
</block-center-colunm>
<block-center-colunm id="block-center-2-2">
<seminar>
<author>Seminar author1</author>
<durable>3</durable>
</seminar>
<seminar>
<author>Seminar author2</author>
<durable>1.5</durable>
</seminar>
<seminar>
<author>Seminar author3</author>
<durable>2</durable>
</seminar>
<seminar>
<author>Seminar author4</author>
<durable>3</durable>
</seminar>
</block-center-colunm>
</block-center-row>
</block-center>
</page>
<!-- ... -->
</content>
XSL file: block-center-1-1.xsl:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="block-center-row-1">
<div class="block-center-row">
<h2>My CD Collection</h2>
<table border="1" width="100%">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:for-each select="
content/page[#id=$pageId]/block-center/
block-center-row[#id='block-center-row-1']/cd
">
<tr>
<td>
<xsl:value-of select="title" />
</td>
<xsl:choose>
<xsl:when test="price > 10">
<td bgcolor="#ff00ff">
<xsl:value-of select="artist" />
</td>
</xsl:when>
<xsl:when test="price > 9">
<td bgcolor="#cccccc">
<xsl:value-of select="artist" />
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:value-of select="artist" />
</td>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:for-each>
</table>
</div>
</xsl:template>
</xsl:stylesheet>
XSL file block-center.xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="block-center-1-1.xsl" />
<xsl:template name="block-center">
<!-- if put here. It work properly -->
<div class="block-center">
<xsl:for-each select="content/page[#id=$pageId]/block-center/block-center-row">
<xsl:choose>
<!-- // I does not work here -->
<xsl:when test="#id='block-center-row-1'">
<xsl:call-template name="block-center-row-1" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</div>
</xsl:template>
</xsl:stylesheet>
I dont know why It does not work (not out put data) if I call <xsl:call-template> inside <xsl:for-each> loop. Otherwise, It's OK.
I have a few remarks to make. First off, it is a bad idea to make format implications in the XML. Having elements that are called <block-center> or <block-center-colunm> is not only unnecessarily verbose, it will also make your head hurt as soon as their contents is not going to be displayed in a block in the center anymore.
Second, let go of <xsl:call-template> and <xsl:for-each>. They may seem convenient if you have procedural programming background, but they are the wrong choice. Use <xsl:apply-templates> instead, it leads to code that's cleaner and easier to understand.
Now to your XSL. Your second XSL (block-center.xsl) - what does it do? Why do you have two separate XSL files? Also, it is missing a variable or parameter declaration. I've used:
<xsl:variable name="pageId" select="'page-1'" />
for my tests. It also has only one template (<xsl:template name="block-center">) that is never actually being called, so it did not do anything for me. I've added
<xsl:template match="/">
<xsl:call-template name="block-center" />
</xsl:template>
so it would at least do anything.
Your other XSL file (block-center-1-1.xsl) has a for-each loop that is not looking at the right context. You already are in the following context when you enter the template "block-center-row-1":
content/page[#id=$pageId]/block-center/block-center-row
so all you need to do in the for-each loop is:
<xsl:for-each select="cd">
and it will start to output all <cd> nodes.
Many thanks for your euthusiasm!
It's now works properly if I change in block-center-1-1.xsl file
TO
OR