Reputation: 1430
I have created a stylesheet that is supposed to selectively copy the contents of an XML document so that I can strip out data that we do not need. I have provided 2 examples below and the stylesheet that we are currently using to do this. The stylesheet works, but I think there is probably a better way of doing it because in the current version I check for the same thing in two different locations (author='John Doe').
The rules for including an xml element in the output is as follows:
<transaction>
<policy>
<insco>CC</insco>
<notepads>
<notepad>
<author>Andy</author>
<notepad>
<notepad>
<author>John Doe</author>
<notepad>
<notepad>
<author>Barney</author>
<notepad>
</notepads>
</policy>
</transaction>
<transaction>
<policy>
<insco>CC</insco>
<notepads>
<notepad>
<author>John Doe</author>
<notepad>
</notepads>
</policy>
</transaction>
<transaction>
<policy>
<insco>CC</insco>
<notepads>
<notepad>
<author>Andy</author>
<notepad>
</notepads>
</policy>
</transaction>
<transaction>
<policy>
<insco>CC</insco>
</policy>
</transaction>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn">
<xsl:template match="*">
<xsl:choose>
<xsl:when test="name()='notepads'">
<xsl:if test="/transaction/policy/insco='CC' and (notepad/author='John Doe')">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:if>
</xsl:when>
<xsl:when test="name()='notepad'">
<xsl:if test="author='John Doe'">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Views: 352
Reputation: 338108
I can think of two ways to do this.
1) identity template, hard coded author name:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- nodepads generally get removed... -->
<xsl:template match="notepad" />
<!-- ...unless their author is 'Jon Doe' -->
<xsl:template match="notepad[author='John Doe']">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
2) modified identity template, XSL key, parameterized author name:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:param name="theAuthor" select="'John Doe'" />
<xsl:key
name="kNotepad" match="notepad[author]"
use="concat(generate-id(..), '|', author)"
/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="
node()[not(self::notepad)]
|key('kNotepad', concat(generate-id(), '|', $theAuthor))
|@*"
/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The second approach requires a little explanation:
<xsl:key>
indexes all <nodepad>
nodes that have an <author>
by their parent's unique ID and the author name<notepads>
is 'id0815'
, then the key to the <notepad>
s you are interested in would be 'id0815|Jon Doe'
<notepad>
: node()[not(self::notepad)]
@*
key()
naturally only ever returns anything at all on <notepads>
elements (because it contains their unique ID)<notepads>
element ('id0815'
in our case), key()
will return its 'Jon Doe'
children only, in all other cases it will turn up emptyUpvotes: 2
Reputation: 60190
Use templates, they're usually more efficient, and avoid name()
checks, they're slow and unreliable (prefixes and namespaces don't work well with those):
<?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"/>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="notepads">
<xsl:if test="(ancestor::policy/insco='CC') and (notepad/author='John Doe')">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="notepad">
<xsl:if test="author='John Doe'">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2