How to group nearby same elements using XSLT version 1 [closed] - xslt

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I need to transform an XML structure to another XML structure by grouping nearby elements using XSLT version 1 and store into a variable for later process.
My current solution:
https://xsltfiddle.liberty-development.net/naZXVF1/3
XML
<?xml version="1.0"?>
<Items>
<Parameter>1</Parameter>
<Parameter>2</Parameter>
<Menu>1</Menu>
<Parameter>3</Parameter>
<Parameter>4</Parameter>
<Menu>2</Menu>
<Menu>3</Menu>
<Parameter>5</Parameter>
<Parameter>6</Parameter>
<Parameter>7</Parameter>
<Parameter>8</Parameter>
</Items>
Expected Result
<Items>
<Parameters>
<Parameter>1</Parameter>
<Parameter>2</Parameter>
</Parameters>
<Menus>
<Menu>1</Menu>
</Menus>
...
</Items>

Either use sibling recursion or use a complicated key to identify the elements belonging together:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="group" match="*[name(preceding-sibling::*[1]) = name()]"
use="generate-id(preceding-sibling::*[name() = name(current())][name(preceding-sibling::*[1]) != name()][1])"/>
<xsl:template match="Items">
<xsl:copy>
<xsl:apply-templates select="*[name(preceding-sibling::*[1]) != name()]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Items/*">
<xsl:element name="{name()}s">
<xsl:copy-of
select=". | key('group', generate-id())"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/naZXVF1/4

Related

XSL selective copy [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have this XML file:
<bases>
<marker>
<name>Main</nane>
<city>Hartford</city>
<tag>current</tag>
</marker>
<marker>
<name>Secondary</nane>
<city>Boston</city>
<tag>none</tag>
</marker>
<marker>
<name>Tertiary</nane>
<city>Bedford</city>
</marker>
</bases>
I want to copy only those markers where the tag element matches "current". So, the output would be this:
<bases>
<marker>
<name>Main</nane>
<city>Hartford</city>
<tag>current</tag>
</marker>
</bases>
I'm an XSLT novice and I can't figure it out. Help, please.
You could do it simply like this :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<!-- Remove all marker elements where element tag value is not 'current' -->
<xsl:template match="marker[not(tag='current')]"/>
<!-- Identity template -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
See it working here : https://xsltfiddle.liberty-development.net/aiynev/2

XPath expression of xslt [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a question about if statemnt for xslt if statement
https://xsltfiddle.liberty-development.net/bwe3c5/38
Here is a link to mine html structure and xslt code.
I do not understand why if statemnt is called only once however i have several circumstances at which statement can be called.
P.S.
Sorry for the wrong first code. Somehow it has shared the wrong one
Your <html> element is in a default namespace xmlns="http://www.w3.org/1999/xhtml". So you have to declate it in your XSLT file and on all of the elements using it:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" indent="no"/>
<?startSampleFile ?>
<!-- xq61.xsl: converts xq60.xml into xq62.xml -->
<xsl:template match="/xhtml:html/xhtml:body/xhtml:table">
<xsl:for-each select="xhtml:tr">
<xsl:value-of select="xhtml:td" />
<xsl:if test="xhtml:td[1] != 'skip'">
<xsl:call-template name="first_column" />
</xsl:if>
</xsl:for-each>
</xsl:template>
<?endSampleFile ?>
<xsl:template name="first_column">
I am here
</xsl:template>
<!-- Copy the other nodes -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
P.S.: You changed your code after I first retrieved the XSLT and XML files. This is against the rules of SO. Include the current state of your code into the question.
It's only being called 1 time because the match='/' only matches the root element in the XML.
This template is never run
<xsl:template match="#*|node()">
<xsl:apply-templates select="*"/>
</xsl:template>

Transform to output xml based on the value of an element in the input xml

I am trying to learn the basics of XSLT, but am stuck on a particular use case. What I want to achieve is to transform one xml file into another xml (I am using XSLT 2.0), but a condition is that the grouping of elements in the output xml is decided by the value of one particular element in the input xml.
I will try to exemplify my question through a made-up example.
Lets say this is an input xml:
<products>
<shoes>
<shoe>
<name>Ecco City</name>
<category>Urban</category>
</shoe>
<shoe>
<name>Timberland Forest</name>
<category>Wildlife</category>
</shoe>
<shoe>
<name>Asics Gel-Kayano</name>
<category>Running</category>
</shoe>
</shoes>
<clothes>
<shorts>
<name>North Face</name>
<category>Wildlife</category>
</shorts>
<shorts>
<name>Adidas Running Shorts</name>
<category>Running</category>
</shorts>
</clothes>
Based on the value of the category element I want to, for each product, list similar products, that is, other products having the same category in the input xml, like this:
<output>
<forSale>
<item>Asics Gel-Kayano</item>
<similarItem>Adidas Running Shorts</similarItem>
</forSale>
</output>
This doesn't seem to be a grouping problem as such. If I understand correctly, you want to do something like:
XSLT 2.0
<xsl:stylesheet version="2.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:key name="product-by-category" match="*" use="category" />
<xsl:template match="/products">
<output>
<xsl:for-each select="*/*">
<forSale>
<item>
<xsl:value-of select="name" />
</item>
<xsl:for-each select="key('product-by-category', category) except .">
<similarItem>
<xsl:value-of select="name" />
</similarItem>
</xsl:for-each>
</forSale>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
Applied to your input example, the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<forSale>
<item>Ecco City</item>
</forSale>
<forSale>
<item>Timberland Forest</item>
<similarItem>North Face</similarItem>
</forSale>
<forSale>
<item>Asics Gel-Kayano</item>
<similarItem>Adidas Running Shorts</similarItem>
</forSale>
<forSale>
<item>North Face</item>
<similarItem>Timberland Forest</similarItem>
</forSale>
<forSale>
<item>Adidas Running Shorts</item>
<similarItem>Asics Gel-Kayano</similarItem>
</forSale>
</output>

HTML Escape some xml tag using xslt

I have some XML like
<ITEM><TITLE>Video: High Stakes for <KW>Obama</KW> & Romney</TITLE></ITEM>
which I would like to translate to the below XML using XSLT.
<ITEM><TITLE>Video: High Stakes for <KW>Obama</KW> & Romney</TITLE></ITEM>
I tried <xls:copy-of select="./TITLE"/> but that is not escaping the XML tags. Any idea?
These sorts of questions always attract a lot of competing answers, because the best answer depends on how generalized you need it to be, and that is not clear from your question.
If you want a super-generalised solution, I will leave that to the regular XSLT SO stars. Or you could just search SO for questions which ask how to serialize/ or stringize XML. There are plenty.
I will offer you a very simple but specific solution, for a very narrow interpretation of your question. For this I will assume that:
You are just interested in serializing the content of the TITLE element.
The element children of TITLE' (such asKW`) are restricted, in that they have no children and no attributes, and are not in a namespace.
With this interpretation, this input document...
<ITEM>
<TITLE>Video: High Stakes for <KW>Obama</KW> & Romney</TITLE>
</ITEM>
...transformed by this XSLT 1.0 style-sheet (works just the same in 2.0)...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TITLE/*">
<xsl:value-of select="concat('<',name(),'>',.,'</',name(),'>')" />
</xsl:template>
</xsl:stylesheet>
...yields...
<ITEM>
<TITLE>Video: High Stakes for <KW>Obama</KW> & Romney</TITLE>
</ITEM>
XSLT doesn't have a specific, direct feature to destruct markup to text (and you have to think well if this is really useful in your case).
This said, here is a short solution using a tiny C# extension function (a similar extension function can easily be written for most other PLs and platforms):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:my="my:my" exclude-result-prefixes="msxsl my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/TITLE/*">
<xsl:value-of select="my:stringize(.)"/>
<xsl:apply-templates/>
</xsl:template>
<msxsl:script language="c#" implements-prefix="my">
public string stringize(XPathNavigator doc)
{
return doc.OuterXml;
}
</msxsl:script>
</xsl:stylesheet>
When this transformation is applied to the provided XML document:
<ITEM><TITLE>Video: High Stakes for <KW>Obama</KW> & Romney</TITLE></ITEM>
the wanted, correct result is produced:
<ITEM>
<TITLE>Video: High Stakes for <KW>Obama</KW> & Romney</TITLE>
</ITEM>
Do note:
This solution flattens out to text the whole subtree rooted in a TITLE element that is a child of the top element of the XML document -- regardless of depth -- which the other posted answer doesn't.
This solution correctly flattens elements with attributes or empty elements -- which the other posted answer -- doesn't.

variable inside a variable in xslt coding [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Is it possible to create a variable inside a variable in xslt??
Is the above thing possible???
Is this what you mean?
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="2.0">
<xsl:variable name="a">
<xsl:variable name="b" select="10"/>
<xsl:value-of select="$b"/>
</xsl:variable>
<xsl:template match="/">
<xsl:value-of select="$a"/>
</xsl:template>
</xsl:stylesheet>
The answer is yes, but the inner variable is in scope only within the definition of the outer variable. So if the definition of the outer variable calls for some complex expression that you'd like to store in a temporary (possibly for debugging purposes), then this is a way to do it.
The answer is: yes. This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="vOuter">
<xsl:variable name="vInner">
<xsl:value-of select="'Content'"/>
</xsl:variable>
<xsl:value-of select="concat('Some ',$vInner)"/>
</xsl:variable>
<xsl:value-of select="$vOuter"/>
</xsl:template>
</xsl:stylesheet>
Output:
Some Content