Here my Xml
<document>
<metadata>
<title>Sign in to my account</title>
</metadata>
<topic>
<conceptuldocument>
<legacybold> Hi hello world </legacybold>
</conceptuldocument>
</topic>
</document>
I only need the title which is under the metadata data tag
all I would need is <h1> sign in to my account</h1>
but i am getting out put html as
<h1>sign in to my account</h1>Hi hello world
here my 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="html" indent="yes"/>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="metadata">
<xsl:apply-templates select="metadata"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="metadata">
<h1>
<xsl:value-of select="title"/>
</h1>
</xsl:template>
</xsl:stylesheet>
C# :
using (StringWriter sw = new StringWriter())
{
transform.Transform(xmldocument.DocumentElement,null, sw);
string html = sw.ToString();
}
output image
xml image
Xslt file image
wondering if any one can help me point what am i missing here , very new to xslt its just been a day.
Simplest fix is to change your entry template to
<xsl:template match="/">
<xsl:apply-templates select="document/metadata"/>
</xsl:template>
Note that your xsl:choose around the xsl:apply-templates is a waste of space. If the element doesn't exist, xsl:apply-templates will do nothing.
Input.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<output>
<orders>
<order>
<id>1</id>
<number>10002</number>
<type>Loading</type>
<date>2013-01-01T02:30:00</date>
</order>
<order>
<id>2</id>
<number>10003</number>
<type>Loading</type>
<date>2013-01-01T010:30:00</date>
</order>
</orders>
<quantities>
<quantity>
<id_order>1</id_order>
<unit>KG</unit>
<value>1000</value>
</quantity>
<quantity>
<id_order>2</id_order>
<unit>PAL</unit>
<value>3</value>
</quantity>
</quantities>
</output>
Output.xml should look like this
<?xml version="1.0" encoding="ISO-8859-1"?>
<output>
<orders>
<order>
<id>1</id>
<number>10002</number>
<type>Loading</type>
<KG>1000</KG>
<PAL>3</PAL>
<M3>1.5</M3>
</order>
<order>
<id>2</id>
<number>10003</number>
<type>Loading</type>
<KG>2000</KG>
<PAL>4</PAL>
</order>
</orders>
</output>
What is the format of XSLT file I need to apply ?
ps: ignore this line, sTu!"#id SO asks me to write more text in this post thinking its all code. ignore this line, sTu!"#id SO asks me to write more text in this post thinking its all code.
The following XSLT does what you need (except formatting):
<?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" encoding="iso-8859-1"/>
<!-- Copy all elements recursively -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- Copy this element with subelements -->
<xsl:template match="order">
<!-- Save ID for queries -->
<xsl:variable name="id" select="id" />
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
<!-- Find all quantity elements by ID -->
<xsl:for-each select="//quantity[id_order=$id]">
<!-- Create element with name set to value of unit element and value of value element -->
<xsl:element name="{unit}">
<xsl:value-of select="value"/>
</xsl:element>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<!-- Skip these elements -->
<xsl:template match="quantities" />
<xsl:template match="date" />
</xsl:stylesheet>
RESULT
<?xml version="1.0" encoding="UTF-8"?>
<output>
<orders>
<order>
<id>1</id>
<number>10002</number>
<type>Loading</type>
<KG>1000</KG>
</order>
<order>
<id>2</id>
<number>10003</number>
<type>Loading</type>
<PAL>3</PAL>
</order>
</orders>
</output>
I have this data in source XML:
<Firma ID_FIRMY="15" ROLE_FIRMY="O " KOD_FIRMY="Tomášov">
This is my XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:template match="root/Firma">
<MoneyData>
<xsl:copy-of select="#ID_FIRMY"/>
<xsl:copy-of select="#KOD_FIRMY"/>
</MoneyData>
</xsl:template>
</xsl:stylesheet>
This is my XML output:
<?xml version="1.0" encoding="utf-8"?>
<MoneyData ID_FIRMY="15" KOD_FIRMY="Tomášov"/>
But I need this output: (change names..)
<?xml version="1.0" encoding="utf-8"?>
<MoneyData KodAgendy="15" HospRokOd="Tomášov"/>
How do I do that?
Write templates to transform the attributes:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:template match="root/Firma">
<MoneyData>
<xsl:apply-templates select="#* | node()"/>
</MoneyData>
</xsl:template>
<xsl:template match="Firma/#ID_FIRMY">
<xsl:attribute name="KodAgendy"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
<xsl:template match="Firma/#KOD_FIRMY">
<xsl:attribute name="HospRokOd"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
<xsl:template match="#ROLE_FIRMY"/>
</xsl:stylesheet>
I am editing an xslt in C#.
It has a template "Get" defined in it.
I want to call this template and pass it into a variable.
Template:
<xsl:template name="Get">
<xsl:param name="varMonth" />
<xsl:choose>
<xsl:when test="$varMonth='JAN'">
<xsl:value-of select="'A'" />
</xsl:when>
</xsl:choose>
</xsl:template>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<DocumentElement>
<PositionMaster>
<xsl:variable name="varName">
<xsl:value-of select="''" />
</xsl:variable>
</PositionMaster>
</DocumentElement>
</xsl:template>
</xsl:stylesheet>
Code:
I am getting a string as an input to the param of the template
string input = "A";
XmlDocument xslDoc = new XmlDocument();
xslDoc.Load("a.xslt");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xslDoc.NameTable);
nsMgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
XmlElement valueOf = (XmlElement)xslDoc.SelectSingleNode("/xsl:stylesheet/xsl:template[#match = '/']/DocumentElement/PositionMaster/xsl:variable[#name = "varName"]/xsl:value-of", nsMgr);
if (valueOf != null)
{
// What should i write here to get the below modified XSLT
}
Required XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<DocumentElement>
<PositionMaster>
<xsl:variable name="varName">
<xsl:call-template name="Get">
<xsl:with-param name="Month" select="input"/>
</xsl:call-template>
</xsl:variable>
</PositionMaster>
</DocumentElement>
</xsl:template>
</xsl:stylesheet>
Am I right in understanding that you want to transform the stylesheet using C# code? That seems crazy; you are using XSLT, so you have an XML transformation language at your disposal: use it!
However, I'm confused because neither your original stylesheet nor your modified stylesheet is valid XSLT. You can't have a <DocumentElement> element as a child of xsl:stylesheet; it surely needs to be inside a template.
Transforming XSLT stylesheets using XSLT is common practice and it can be a smart approach to some problems. However, it is often done when there are better techniques available, for example adding stylesheet parameters (global xsl:param elements).
I've got the following XML structure :
<Article>
<id>1</id>
<line>L11</line>
<line>L12</line>
<line>L13</line>
</Article>
<Article>
<id>2</id>
<line>L21</line>
<line>L22</line>
<line>L23</line>
</Article>
I want to use XSLT to iterate over all the lines of only one article at a time so that I can achieve the following structure : (every article is converted into an order, and its lines are converted to line structures in the new structure)
<orders>
<order>
<id>1</id>
<order_line>L11</order_line>
<order_line>L12</order_line>
<order_line>L13</order_line>
</order>
<order>
<id>2</id>
<order_line>L21</order_line>
<order_line>L22</order_line>
<order_line>L23</order_line>
</order>
</orders>
With XSLT, try to think of the task at hand as a set of patterns or rules you have to match, and the actions to be taken each time such a pattern is encountered. You can usually let the runtime worry about looping, etc, to discover patterns.
In your specific case, you've described two patterns you want special logic. Every time there is the element Article, you wish to apply the rule to change its name to order.
Every time the element line is encountered as a child of Article, replace it with order_line. For any other pattern, you just want to copy the contents as they were in the original document:
<!-- Match element Article, and whenever it's encountered, insert an 'order' element, and copy the contents of Article -->
<xsl:template match="Article">
<order> <xsl:apply-templates/> </order>
</xsl:template>
<!-- Match element 'line', and whenever it's encountered, insert an 'order_line' element, and copy the contents -->
<xsl:template match="Article/line">
<order_line> <xsl:apply-templates/> </order_line>
</xsl:template>
<!-- Match any other element we haven't specified explicity, and copy it verbatim -->
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
This is a straightforward transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<orders>
<xsl:apply-templates/>
</orders>
</xsl:template>
<xsl:template match="Article">
<order>
<xsl:apply-templates/>
</order>
</xsl:template>
<xsl:template match="line">
<order_line>
<xsl:apply-templates/>
</order_line>
</xsl:template>
<xsl:template match="id">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
EDIT: A general root element rule.
This complete XSLT 1.0 transformation:
<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="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<orders>
<xsl:apply-templates/>
</orders>
</xsl:template>
<xsl:template match="Article">
<order>
<xsl:apply-templates/>
</order>
</xsl:template>
<xsl:template match="line">
<order_line>
<xsl:apply-templates/>
</order_line>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document (wrapped into a single top element to make it well-formed):
<t>
<Article>
<id>1</id>
<line>L11</line>
<line>L12</line>
<line>L13</line>
</Article>
<Article>
<id>2</id>
<line>L21</line>
<line>L22</line>
<line>L23</line>
</Article>
</t>
produces the wanted, correct result:
<orders>
<order>
<id>1</id>
<order_line>L11</order_line>
<order_line>L12</order_line>
<order_line>L13</order_line>
</order>
<order>
<id>2</id>
<order_line>L21</order_line>
<order_line>L22</order_line>
<order_line>L23</order_line>
</order>
</orders>
Explanation:
The identity rule copies every node "as-is".
The identity rule is overriden by three templates, each of which matches a particular kind of element (the top element, Article and line) and simply renames the element, respectively to: orders, order and order_line.
This is just of the top of my head but I think you can do it this way:
<orders>
<xsl:for-each select="//Article">
<order>
<id><xsl:value-of select="./id"/></id>
<xsl:for-each select="./line">
<order_line><xsl:value-of select="child::text()" /></order_line>
</xsl:for-each>
</order>
</xsl:for-each>
</orders>
Anyway, it should be enough to get you started. There is only a for-each loop in XSLT though, no for loop with a counter.
Your source XML file is not well-formed. For clarity, my response assumes you've wrapped it in a element. This is a pretty trivial XML transformation so I've included some comments explaining what each line of code is doing.
<!-- change the template match xpath to whatever the root xpath is in your document -->
<xsl:template match="root">
<orders>
<!-- loop over each Article -->
<xsl:for-each select="Article">
<order>
<!-- pass id through -->
<xsl:copy-of select="id"/>
<!-- loop over each line -->
<xsl:for-each select="line">
<!-- create an <order_line> node -->
<order_line>
<!-- get the value of the current <line> -->
<xsl:value-of select="."/>
</order_line>
</xsl:for-each>
</order>
</xsl:for-each>
</orders>
</xsl:template>
Try this, but I am not a xslt expert :)
<?xml version="1.0" encoding="utf-8"?>
<xsl:template match="/" name="A">
<orders>
<xsl:for-each select="Articles/Article">
<order>
<id>
<xsl:value-of select="id" />
</id>
<xsl:for-each select="line">
<order_line>
<xsl:value-of select="node()"></xsl:value-of>
</order_line>
</xsl:for-each>
</order>
</xsl:for-each>
</orders>
</xsl:template>
The correct way to do "looping" in XSLT is to let the XSLT processor walk the document tree for you. Anything else is fighting against the nature of XSLT.
Here's a (near-) complete solution:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<orders><xsl:apply-templates/></orders>
</xsl:template>
<xsl:template match="Article">
<order>
<id><xsl:value-of select="id"/></id>
<xsl:apply-templates select="line"/>
</order>
</xsl:template>
<xsl:template match="Article/line">
<order_line><xsl:value-of select="."/></order_line>
</xsl:template>
</xsl:stylesheet>