Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>XSLT lets you recursively traverse the node tree. Whilst traversing your tree, you can get XSLT to process your nodes by creating template rules that are more specific than other template rules.</p> <p>The problem you are trying to solve is in transforming your XML tree with some slight differences. A good start is to take the <a href="http://en.wikipedia.org/wiki/Identity_transform#Using_XSLT" rel="nofollow">identity transform</a>:</p> <pre><code>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; &lt;xsl:template match="@*|node()"&gt; &lt;xsl:copy&gt; &lt;xsl:apply-templates select="@*|node()"/&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p>This identity transform will simply produce the XML output that is the same as the input XML. It matches and copies every XML node as it is. You then mould your output step-by-step until you get what you want. See documentation for <code>&lt;xsl:copy/&gt;</code>.</p> <p>The exception to this copying you want to make is when you come across elements that do not have any child nodes. To match any element, we use <code>*</code>. to match no elements, we use <code>not(*)</code>. To match any element with no elements, we thus use <code>*[not(*)]</code>. In fact, these rules are defined by the <a href="http://en.wikipedia.org/wiki/XPath" rel="nofollow">XPath</a> query language which XSLT uses. Let's try the following XSLT against your XML:</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt; &lt;xsl:template match="*[not(*)]"&gt; &lt;found-an-element-with-no-children/&gt; &lt;/xsl:template&gt; &lt;xsl:template match="@*|node()"&gt; &lt;xsl:copy&gt; &lt;xsl:apply-templates select="@*|node()"/&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p>We get:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;DEV&gt; &lt;HDR&gt; &lt;found-an-element-with-no-children/&gt; &lt;found-an-element-with-no-children/&gt; &lt;/HDR&gt; &lt;DSC&gt; &lt;found-an-element-with-no-children/&gt; &lt;/DSC&gt; &lt;/DEV&gt; </code></pre> <p>The nice thing is that any one node can only match against a single template rule at a time. And we look much closer to where we want to be now.</p> <p>Here's where <code>&lt;xsl:copy/&gt;</code> comes in. We'll use it now because we want to copy the original element's name.</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt; &lt;xsl:template match="*[not(*)]"&gt; &lt;xsl:copy&gt; &lt;found-an-element-with-no-children/&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;xsl:template match="@*|node()"&gt; &lt;xsl:copy&gt; &lt;xsl:apply-templates select="@*|node()"/&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p>Now we get to:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;DEV&gt; &lt;HDR&gt; &lt;ApID&gt;&lt;found-an-element-with-no-children/&gt;&lt;/ApID&gt; &lt;STAT&gt;&lt;found-an-element-with-no-children/&gt;&lt;/STAT&gt; &lt;/HDR&gt; &lt;DSC&gt; &lt;Cap&gt;&lt;found-an-element-with-no-children/&gt;&lt;/Cap&gt; &lt;/DSC&gt; &lt;/DEV </code></pre> <p>Now add an attribute to our newly created node, and include in it the text contents of the node that we matched just now:</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt; &lt;xsl:template match="*[not(*)]"&gt; &lt;xsl:copy&gt; &lt;xsl:attribute name="V"&gt; &lt;xsl:value-of select="."/&gt; &lt;/xsl:attribute&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;xsl:template match="@*|node()"&gt; &lt;xsl:copy&gt; &lt;xsl:apply-templates select="@*|node()"/&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p>And it looks like we're here:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;DEV&gt; &lt;HDR&gt; &lt;ApID V="value1"/&gt; &lt;STAT V="value2"/&gt; &lt;/HDR&gt; &lt;DSC&gt; &lt;Cap V="value3"/&gt; &lt;/DSC&gt; &lt;/DEV&gt; </code></pre> <p>Now a couple of pointers:</p> <ol> <li>None of your <code>ApID</code>, <code>STAT</code> and <code>Cap</code> will be able to copy its old attributes. You will want to include <code>&lt;xsl:apply-templates select="@*"/&gt;</code> to include those attributes.</li> <li>And when you include those attributes, what happens if the original input contains a <code>V</code> attribute?</li> <li>You might want to additionally consider what happens when the tags that you match have no text - and why.</li> </ol>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload