I want to read an XML file inside XSLT and check its nodes. if they match the value of XML node to which I am applying the transform, then grab the value of the XML node and use it to construct a new XML structure.
Here is an example to illustrate my problem. I think many people can use this question for reference to achieve similar functionality.
Referenced.xml
<xml>
<root>
<Id id = "1">
<fields>
<field>
<name> Name1 </name>
<value> Val1 </value>
</field>
<field>
<name> Name2 </name>
<value> Val2 </value>
</field>
</fields>
</Id>
<Id id = "2">
...
</Id>
</root>
</xml>
Xml.xml
<XML>
<Fields>
<Id id = "1">
<F1> Value1 </F1>
<F2> Value2 </F2>
<F1> Value3 </F1>
<F4> Value4 </F4>
</Id>
</Fields>
</XML>
Now, I want to create a transform which will iterate through the XML file (Referenced.xml
) and check where Id inside the both xml's match and then, inside that id, Name1 = F1
and wherever it is then, fetch 'value' for that 'name' and create an XML structure like
<outputXml>
<Field id="Val1">
<val> Value1 </val>
</Field>
<Field id="Val2">
<val> Value2 </val>
</Field> ... and so on
</outputXml>
I know I have to use document(), but I am not sure how do you iterate through the Referenced.xml
inside xsl and use if, else to achieve the functionality needed ?
Check this one:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="file1" select="document('Referenced.xml')"/>
<xsl:param name="file2" select="document('Xml.xml')"/>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<outputXml>
<xsl:for-each select="$file1//Id">
<xsl:variable name="ReferencedID" select="@id"/>
<xsl:choose>
<xsl:when test="$ReferencedID = $file2//Id/@id">
<xsl:for-each select="fields/field">
<Field id="{normalize-space(value)}"><xsl:value-of select="value"/></Field>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</outputXml>
</xsl:template>
</xsl:stylesheet>
to get output:
<outputXml>
<Field id=" Val1 "> Val1 </Field>
<Field id=" Val2 "> Val2 </Field>
</outputXml>
Here's a piece of working code:
<!-- loads a file like resources/strings-en.xml into a variable document-->
<xsl:variable
name="messages"
select="document(concat('resources/strings-', $lang, '.xml'))/my:strings"
/>
...
<!-- uses the loaded document for selecting -->
<xsl:template name="localized-string">
<xsl:param name="name"/>
<xsl:value-of select="$messages/my:string[@name=$name]"/>
</xsl:template>
As you may see, once you have read a document into a variable, it looks like a normal document, you apply XPath expressions to traverse it, etc.
Try this
Your XML FILE Chapters.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="ditaXSL.xsl"?>
<map>
<title>Syncro phone user guide</title>
<topicref href="gettingStarted.dita"/>
</map>
your XSl name : ditaXSL.xsl
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="Functions"
version="2.0">
<xsl:template match="map">
<html>
<title>
<xsl:value-of select="title" />
</title>
<h4>
<xsl:value-of select="title" />
</h4>
<body>
<table>
<tr>
<th>TOPIC REF</th>
</tr>
<xsl:for-each select="topicref">
<tr>
<td>
<xsl:apply-templates select="document(@href)/topic" />
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="topic">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="title">
Chapter :
<h6>
<xsl:value-of select="." />
</h6>
</xsl:template>
<xsl:template match="body">
Description :
<h5>
<xsl:value-of select="." />
</h5>
</xsl:template>
</xsl:stylesheet>
Example gettingStarted.dita file mentioned in xml file.
<?xml version="1.0" encoding="UTF-8"?>
<topic>
<title>Getting started</title>
<body>This is introduction</body>
</topic>