Reputation: 109
XML is generated dynamically in a variable myvar
.
Then I'd like to select the Line
nodes where MyDate != '99991231'
.
This does not work:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="myvar">
<output>
<Line><LineNumber>1</LineNumber><MyDate>99991231</MyDate><Amt>10</Amt></Line>
<Line><LineNumber>2</LineNumber><MyDate>20150131</MyDate><Amt>15</Amt></Line>
<Line><LineNumber>3</LineNumber><MyDate>99991231</MyDate><Amt>20</Amt></Line>
<Line><LineNumber>4</LineNumber><MyDate>20161231</MyDate><Amt>30</Amt></Line>
<Line><LineNumber>5</LineNumber><MyDate>99991231</MyDate><Amt>40</Amt></Line>
<Line><LineNumber>6</LineNumber><MyDate>20171231</MyDate><Amt>50</Amt></Line>
<Line><LineNumber>7</LineNumber><MyDate>20140131</MyDate><Amt>60</Amt></Line>
</output>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$myvar[Line/MyDate='99991231']"/>
</xsl:template>
</xsl:stylesheet>
I'd like to obtain :
<output>
<Line><LineNumber>2</LineNumber><MyDate>20150131</MyDate><Amt>15</Amt></Line>
<Line><LineNumber>4</LineNumber><MyDate>20161231</MyDate><Amt>30</Amt></Line>
<Line><LineNumber>6</LineNumber><MyDate>20171231</MyDate><Amt>50</Amt></Line>
<Line><LineNumber>7</LineNumber><MyDate>20140131</MyDate><Amt>60</Amt></Line>
</output>
Any hint ?
Upvotes: 1
Views: 90
Reputation: 29022
Providing a pure and working XSLT-1.0 solution is not that easy because of the Resulting-Tree-Fragment problem with the variable.
So I wrapped the data inside a data island instead of a variable and used the method from here to avoid the namespace being copied by <copy-of>
.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:var="http://some.var" exclude-result-prefixes="var">
<xsl:output method="xml" indent="yes" />
<var:var>
<output>
<Line><LineNumber>1</LineNumber><MyDate>99991231</MyDate><Amt>10</Amt></Line>
<Line><LineNumber>2</LineNumber><MyDate>20150131</MyDate><Amt>15</Amt></Line>
<Line><LineNumber>3</LineNumber><MyDate>99991231</MyDate><Amt>20</Amt></Line>
<Line><LineNumber>4</LineNumber><MyDate>20161231</MyDate><Amt>30</Amt></Line>
<Line><LineNumber>5</LineNumber><MyDate>99991231</MyDate><Amt>40</Amt></Line>
<Line><LineNumber>6</LineNumber><MyDate>20171231</MyDate><Amt>50</Amt></Line>
<Line><LineNumber>7</LineNumber><MyDate>20140131</MyDate><Amt>60</Amt></Line>
</output>
</var:var>
<xsl:template match="/">
<output>
<xsl:apply-templates select="document('')/xsl:stylesheet/var:var/output/Line[MyDate != '99991231']"/>
</output>
</xsl:template>
<!-- Copy elements - solution from the second SO answer -->
<xsl:template match="*" priority="-1">
<xsl:element name="{name()}">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<!-- Copy all other nodes -->
<xsl:template match="node()|@*" priority="-2">
<xsl:copy />
</xsl:template>
</xsl:stylesheet>
This gives the desired output:
<?xml version="1.0"?>
<output>
<Line>
<LineNumber>2</LineNumber>
<MyDate>20150131</MyDate>
<Amt>15</Amt>
</Line>
<Line>
<LineNumber>4</LineNumber>
<MyDate>20161231</MyDate>
<Amt>30</Amt>
</Line>
<Line>
<LineNumber>6</LineNumber>
<MyDate>20171231</MyDate>
<Amt>50</Amt>
</Line>
<Line>
<LineNumber>7</LineNumber>
<MyDate>20140131</MyDate>
<Amt>60</Amt>
</Line>
</output>
Upvotes: 2
Reputation: 116959
Since you seem to be using XSLT 1.0, you should try it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:variable name="myvar">
<Line><LineNumber>1</LineNumber><MyDate>99991231</MyDate><Amt>10</Amt></Line>
<Line><LineNumber>2</LineNumber><MyDate>20150131</MyDate><Amt>15</Amt></Line>
<Line><LineNumber>3</LineNumber><MyDate>99991231</MyDate><Amt>20</Amt></Line>
<Line><LineNumber>4</LineNumber><MyDate>20161231</MyDate><Amt>30</Amt></Line>
<Line><LineNumber>5</LineNumber><MyDate>99991231</MyDate><Amt>40</Amt></Line>
<Line><LineNumber>6</LineNumber><MyDate>20171231</MyDate><Amt>50</Amt></Line>
<Line><LineNumber>7</LineNumber><MyDate>20140131</MyDate><Amt>60</Amt></Line>
</xsl:variable>
<xsl:template match="/">
<output>
<xsl:copy-of select="exsl:node-set($myvar)/Line[MyDate != '99991231']"/>
</output>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 111491
To copy from $myvar
those Line
elements whose MyDate
child does not equal 99991231
:
<xsl:copy-of select="$myvar/output/Line[MyDate!='99991231']"/>
You'll also have to wrap the selected elements in a common element to generate well-formed XML.
Upvotes: 2