XSLT Create single node from group of nodes

Russ Suter
Russ Suter used Ask the Experts™
on
I am building an XSL stylesheet and I've run into an issue. The source document has a collection of elements which may or may not contain a specific value. I need to create a single XML node in the destination file that flags whether this node exists or not. The attached code shows an example of what I mean but I will try to explain further.

The source XML contains a series of <label> tags which each contain a single <text> tag. (I know, bad XML which is why I'm trying to convert it.) What I need is some way of translating such that my output file contains a <priority>low</priority> tag where the <label><text>3FGA</text></label> does NOT exist and a <priority>high</priority> where 3FGA DOES exist. How can I do this?
Source XML
<instance>
  <label>
    <text>FTM</text>
  </label>
  <label>
    <text>FTA</text>
  </label>
</instance>
<instance>
  <label>
    <text>FTM</text>
  </label>
  <label>
    <text>FGA</text>
  </label>
  <label>
    <text>3FGA</text>
  </label>
</instance>

Output XML
<task>
  <priority>low</priority>
</task>
<task>
  <priority>hight</priority>
</task>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Please check out the following XSLT. Is that you need or I just did not understand your question?
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
	<xsl:template match="instance">
		<task>
		  <priority>
		    <xsl:choose>
		       <xsl:when test=".//text[.='3FGA']">height</xsl:when>
		       <xsl:otherwise>low</xsl:otherwise>
		    </xsl:choose>
		  </priority>
		</task>
 	</xsl:template>
	
</xsl:stylesheet>

Open in new window

Russ SuterSenior Software Developer

Author

Commented:
The problem there is if there are multiple <label><text> tags I'll get multiple <priority> tags as output. I need a single <priority> tag that is either high or low depending on whether a specific tag exists in the collection in the source document.
The XSLT I posted produces a single "task/priority" elements group on each source "instance" element, not matter how many "label/text" elements groups were inside.
OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

Russ SuterSenior Software Developer

Author

Commented:
I see. I'm sitll fairly new to XSLT. How do I consume the template?
A match-template could be called by two ways:
1) via the <xsl:apply-templates select="......"/> element
2) by the embedded in the XSLT default template, which tries to find an appropriate template for each node it sees in its recursive source XML tree traversing.

In the sample I posted, the second way is in use - you can see the template for the "instance" element, but you don't see the starting template. I did that because you provided a not well-formed XML - without the root element so I did not know what elements are parents for the "instance".

To consume the sample template you paste the xsl:template element body to your XSLT and do
<xsl:apply-templates select="instance"/> from some other template.
Russ SuterSenior Software Developer

Author

Commented:
I'm missing something. Can I send you the source and my XSLT and have you fix what I'm doing wrong?
Sure, attach your files
Russ SuterSenior Software Developer

Author

Commented:
Here is the actual source file and my XSLT file
source.xml
translator.xsl
I assumed, your goal is to insert the task/priority group as a child of the Classifications element.
Note the line 122 where I made the changes.
translator.xsl
Russ SuterSenior Software Developer

Author

Commented:
Excellent! It's working perfectly now. Thanks!
you're welcome!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial