there is that XML Node
<svg>
<g transform="translate(113.63-359.13)">
<use fill="#f00" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
</svg>
which can be found by this Xpath
/svg/g[text="ProcessOutbound"]/use
also this work fine
/svg/g[text="ProcessOutbound"]/use/#fill
but for some reasons that xsl is not replaceing #f00 with #00f which is what have tired
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match='/svg/g[text="ProcessOutbound"]/use'>
<xsl:attribute name='fill'>
<xsl:value-of select="'$blue'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
actually the whole svg file is copied but the fill attribute is not replaced. I tried to achive a copy but with the replaced fill value
What is the correct way to replace attribut values with constant values by xsl ?
So the expected result should look like
<g transform="translate(113.63-359.13)">
<use fill="#00f" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
There are a few things incorrect with your XSLT:
It is trying to replace the whole 'use' element with an attribute.
You are using two pairs of quotes around $blue, which causes it to be treated as a string.
You are not using namespaces even though your XML uses a namespace.
Please try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match='svg:g[svg:text = "ProcessOutbound"]/svg:use/#fill'>
<xsl:attribute name='fill'>
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
When run on your sample input, the result is:
<svg xmlns:xlink="...">
<g transform="translate(113.63-359.13)">
<use xlink:href="#D" fill="#00f" />
<g transform="translate(72.59-8.504)">
<use xlink:href="#E" xmlns:xlink="x" />
<path fill="#f00" d="m6.04 526.26h19.843v4.961h-19.843z" stroke-width=".24" stroke-linecap="round" stroke-linejoin="round" stroke="#000" />
<use xlink:href="#F" />
</g>
<text font-family="Arial" fill="#000" font-size="8" y="527.6" x="20.41">ProcessOutbound</text>
</g>
</svg>
http://www.xsltcake.com/slices/d8pdoi
If I am guessing correctly and your input is a valid SVG document, then all its elements are in the SVG namespace. IOW, your input example should actually look like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(113.63-359.13)">
<use fill="#f00" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
</svg>
And then your XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="blue" select="'#00f'"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="svg:g[svg:text='ProcessOutbound']/svg:use/#fill">
<xsl:attribute name='fill'>
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Assuming a well-formed input (the prefix xlink: is not bound because you did not include its namespace definition), use the stylesheet below.
Rather than matching the element use, directly match the node you'd like to modify, the fill attribute of use.
Stylesheet
Your question suggests that the second template should actually match /svg/g[8]/use/#fill if I understood correctly.
<xsl:stylesheet version="1.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:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/svg/g/use/#fill">
<xsl:attribute name="fill">
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
XML Output
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(113.63-359.13)">
<use fill="#00f" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
</svg>
EDIT: As mentioned in a comment, try the following stylesheet if your SVG elements actually are in a namespace:
Stylesheet
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/svg:svg/svg:g/svg:use/#fill">
<xsl:attribute name="fill">
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Try with this,
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/svg/g[contains(text, 'ProcessOutbound')]/use">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:attribute name='fill'>
<xsl:value-of select="$blue"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If this not meeting u r requirement, provide u r simple required text.
Related
I want to transform a source xml into a target xml where certain matches from the source xml are included in different context in the target xml. For example I have a source xml like:
<shiporder>
<shipto>orderperson1</shipto>
<shipto>orderperson1</shipto>
<city>London</city>
</shiporder>
On this source xml I apply the following stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:call-template name="root" />
</xsl:template>
<xsl:template name="root">
<root>
<xsl:apply-templates select="/shiporder"/>
<xsl:call-template name="Customer"/>
</root>
</xsl:template>
<xsl:template name="Customer">
<Customer>
<!--<xsl:apply-templates select="/shiporder"/>-->
</Customer>
</xsl:template>
<xsl:template match="/shiporder">
<xsl:apply-templates select="shipto"/>
</xsl:template>
<xsl:template match="/shiporder/shipto">
<Address>
<xsl:apply-templates select="text()"/>
</Address>
</xsl:template>
</xsl:stylesheet>
In the template of name Customer I like to apply a template like:
<xsl:template match="/shiporder">
<xsl:apply-templates select="city"/>
</xsl:template>
<xsl:template match="/shiporder/city">
<City>
<xsl:apply-templates select="text()"/>
</City>
</xsl:template>
But I already defined a template with match /shiporder. So I don't know how to design a stylesheet where both templates with the same match exists in their own context?
If you use mode, like #michael.hor257k suggested you can differentiate between two or more templates that match on the same element but with different results.
In your case that could end up looking like this:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:call-template name="root" />
</xsl:template>
<xsl:template name="root">
<root>
<xsl:apply-templates select="/shiporder" mode="root"/>
<xsl:call-template name="Customer"/>
</root>
</xsl:template>
<xsl:template name="Customer">
<Customer>
<xsl:apply-templates select="/shiporder" mode="customer"/>
</Customer>
</xsl:template>
<xsl:template match="/shiporder" mode="root">
<xsl:apply-templates select="shipto"/>
</xsl:template>
<xsl:template match="/shiporder" mode="customer">
<xsl:apply-templates select="city"/>
</xsl:template>
<xsl:template match="shipto">
<Address>
<xsl:apply-templates select="text()"/>
</Address>
</xsl:template>
<xsl:template match="city">
<City>
<xsl:apply-templates select="text()"/>
</City>
</xsl:template>
</xsl:stylesheet>
Obviously all credits here go to Michael for pointing this out first.
This is my xml file:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="try.xsl"?>
<oneday>
<team1 id="1" team="India">
<team2 id="2" team="gujarat">
<team3 id="3" team="guj11"></team3>
</team2>
</team1>
</oneday>
This is my xsl file:
<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:output method="text" />
<xsl:template match="*">
<xsl:value-of select="local-name()"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()[normalize-space(.)]">
<xsl:value-of select="concat(':', .)"/>
</xsl:template>
</xsl:stylesheet>
This is my output:
oneday
team1
team2
team3
But I want to output something like this:
oneday
team1:India
team2:Gujarat
team3:Guj11
How's this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="*">
<xsl:apply-templates select="ancestor::*" mode="spacing" />
<xsl:value-of select="local-name()"/>
<xsl:if test="#team">
<xsl:value-of select="concat(':', #team)"/>
</xsl:if>
<xsl:text>
</xsl:text>
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="*" mode="spacing">
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
When run on your sample XML, this produces:
oneday
team1:India
team2:gujarat
team3:guj11
When run on a slightly more complex XML:
<oneday>
<team1 id="1" team="India">
<team2 id="2" team="gujarat">
<team3 id="3" team="guj11"></team3>
</team2>
<team6 team="Mumbai" />
</team1>
<team4 team="France">
<team5 team="Paris" />
</team4>
</oneday>
It produces:
oneday
team1:India
team2:gujarat
team3:guj11
team6:Mumbai
team4:France
team5:Paris
XML coding is given below
<math>
<mn>
<mphantom>12</mphantom>
</mn>
</math>
Output required:
<?xml version='1.0' encoding='UTF-8'?>
<math>|phantom1||phantom2|</math>
XSLT tried:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cl="http://xml.cengage-learning.com/cendoc-core"
xmlns:mml="http://www.w3.org/1998/Math/MathML"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" encoding="UTF-8" indent="no" />
<xsl:strip-space elements="*" />
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="mn">
<xsl:variable name="pText" select="." />
<xsl:variable name="numst" select="2" />
<xsl:choose>
<xsl:when test="not(string-length($pText))>0">
<xsl:value-of select="$pText" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="ConcatStr" select="substring($pText,$numst)" />
<xsl:variable name="FinalStr" select="substring-before($pText,$ConcatStr)" />
<xsl:text disable-output-escaping="yes">|phantom</xsl:text>
<xsl:value-of select="$FinalStr" />
<xsl:text disable-output-escaping="yes">|</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="mphantom">
<xsl:apply-templates />
</xsl:template>
</xsl:stylesheet>
I used the above XSLT to transform but I am getting only the first number. But I need to use it as recursive. I am using XSLT 1.0. Kindly suggest
Here is a simpler, non-recursive solution, using the Piez method:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="mphantom">
<math>
<xsl:variable name="vCur" select="."/>
<xsl:for-each select=
"(document('')//node()|document('')//#*|document('')//namespace::*)
[not(position() > string-length($vCur))]
">
<xsl:value-of select="concat('|', substring($vCur, position(), 1),'|')"/>
</xsl:for-each>
</math>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<math>
<mn>
<mphantom>12</mphantom>
</mn>
</math>
the wanted, correct result is produced:
<math>|1||2|</math>
II. For completeness, here is an XSLT 2.0 solution:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="mphantom">
<math>
<xsl:value-of separator="" select=
"for $i in 1 to string-length()
return
concat('|', substring(., $i, 1), '|')
"/>
</math>
</xsl:template>
</xsl:stylesheet>
Try this..
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output 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="mn[mphantom]" name="phant">
<xsl:param name="chars" select="mphantom" />
<xsl:value-of select="concat('|phantom',substring($chars,1,1),'|')" />
<xsl:if test="substring($chars,2)">
<xsl:call-template name="phant">
<xsl:with-param name="chars" select="substring($chars,2)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I have some XML like this:
<root>
<do-not-sort>
<z/>
<y/>
</do-not-sort>
<sortable>
<e f="fog" h="bat" j="cat">
<n n="p"/>
<m n="p"/>
</e>
<d b="fop" c="bar" k="cab">
<m o="p"/>
<m n="p"/>
</d>
</sortable>
</root>
I want to sort the children of the "sortable" element by their textual representation, to end up with this:
<root>
<do-not-sort>
<z/>
<y/>
</do-not-sort>
<sortable>
<d b="fop" c="bar" k="cab">
<m n="p"/>
<m o="p"/>
</d>
<e f="fog" h="bat" j="cat">
<m n="p"/>
<n n="p"/>
</e>
</sortable>
</root>
I am currently doing this by applying the following XSLT template:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="#* | /">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="#*" />
<xsl:value-of select="normalize-space(text()[1])" />
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="sortable//*">
<xsl:copy>
<xsl:apply-templates select="#*" />
<xsl:value-of select="normalize-space(text()[1])" />
<xsl:apply-templates select="*">
<xsl:sort data-type="text" select="local-name()" />
<xsl:sort data-type="text" select="#*" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The sorting works correctly, but if the sorted elements have a lot of attributes, the later attributes each wrap onto a new line, for example:
<sortable>
<this is="an" element="with" a="lot" of="attributes"
and="the"
excess="ones"
each="wrap"
onto="their"
own="line"/>
How do I keep all these attributes on the same line, i.e.
<sortable>
<this is="an" element="with" a="lot" of="attributes" and="the" excess="ones" each="wrap" onto="their" own="line"/>
How do I keep all these attributes on
the same line
In your code, replace:
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
with
<xsl:output method="xml" encoding="UTF-8" />
Of course, this will produce the complete output on a single line! At the moment of writing this XSLT 2.0 still doesn't have a finer grained control over the serialization of the output.
In case you need some elements indented and some not, then you will have to provide your own post-processing (and this post-processing may be easier to write with something different from XSLT).
Update:
Actually, using Saxon 9.1.07 and
<xsl:output method="html" encoding="UTF-8" />
where the complete transformation is:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" />
<xsl:template match="#* | /">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="#*" />
<xsl:value-of select="normalize-space(text()[1])" />
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="sortable//*">
<xsl:copy>
<xsl:apply-templates select="#*" />
<xsl:value-of select="normalize-space(text()[1])" />
<xsl:apply-templates select="*">
<xsl:sort data-type="text" select="local-name()" />
<xsl:sort data-type="text" select="#*" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
and the source XML document is:
<root>
<do-not-sort>
<z></z>
<y></y>
</do-not-sort>
<sortable>
<this is="an" element="with" a="lot" of="attributes" and="the" excess="ones" each="wrap" onto="their" own="line"></this>
<e f="fog" h="bat" j="cat"></e>
<d b="fop" c="bar" k="cab"></d>
<d b="foo" c="baz" k="cap"></d>
</sortable>
</root>
I get the output with the wanted indentation:
<root>
<do-not-sort>
<z></z>
<y></y>
</do-not-sort>
<sortable>
<this is="an" element="with" a="lot" of="attributes" and="the" excess="ones" each="wrap" onto="their" own="line"></this>
<e f="fog" h="bat" j="cat"></e>
<d b="fop" c="bar" k="cab"></d>
<d b="foo" c="baz" k="cap"></d>
</sortable>
</root>
If you are using Saxon, and want to avoid everything being on one line, you can use the 'line-length' attribute, like this:
<xsl:output xmlns:saxon="http://saxon.sf.net/" indent="yes" saxon:line-length="2000"/
However, be aware that this only works on the Saxon PE (Professional) edition. See here for details:
http://www.saxonica.com/products/products.xml
If you are using the HE (Home) version, you will get an error like this:
Transformation failed: Requested feature (custom serialization {http://saxon.sf.net/}line-length) requires Saxon-PE
I have the following XML:
<DEVICEMESSAGES>
<VERSION xml="1" checksum="" revision="0" envision="33050000" device="" />
<HEADER id1="0001" id2="0001" content="Nasher[<messageid>]: <!payload>" />
<MESSAGE level="7" parse="1" parsedefvalue="1" tableid="15" id1="24682" id2="24682" eventcategory="1003010000" content="Access to <webpage> was blocked due to its category (<info> by <hostname>)" />
</DEVICEMESSAGES>
I am using the following XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="DEVICEMESSAGES/HEADERS">
<xsl:value-of select="#id2"/>,<xsl:text/>
<xsl:value-of select="#content"/>,<xsl:text/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
I get the following output:
0001 , Nasher[<messageid>]: <!payload>
whereas I need the column headings, too:
id2, content
0001 , Nasher[<messageid>]: <!payload>
If DEVICEMESSAGES is the document element and you have repeating MESSAGE elements, then this should work:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="DEVICEMESSAGES">
<xsl:text>id2,content,
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="DEVICEMESSAGES/HEADER">
<xsl:value-of select="#id2"/>,<xsl:text/>
<xsl:value-of select="#content"/>,<xsl:text/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
If you have a different document element, then adjust the template to match on that.
For instance, if the document element is doc and you had 1 to N number of DEVICEMESSAGES elements:
<doc>
<DEVICEMESSAGES>
<VERSION xml="1" checksum="" revision="0" envision="33050000" device="" />
<HEADER id1="0001" id2="0001" content="Nasher[<messageid>]: <!payload>" />
<MESSAGE level="7" parse="1" parsedefvalue="1" tableid="15" id1="24682" id2="24682" eventcategory="1003010000" content="Access to <webpage> was blocked due to its category (<info> by <hostname>)" />
</DEVICEMESSAGES>
<DEVICEMESSAGES>
<VERSION xml="1" checksum="" revision="0" envision="33050000" device="" />
<HEADER id1="0002" id2="0002" content="Nasher[<messageid>]: <!payload>" />
<MESSAGE level="7" parse="1" parsedefvalue="1" tableid="15" id1="24682" id2="24682" eventcategory="1003010000" content="Access to <webpage> was blocked due to its category (<info> by <hostname>)" />
</DEVICEMESSAGES>
</doc>
then you could use this:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="doc">
<xsl:text>id2,content,
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="DEVICEMESSAGES/HEADER">
<xsl:value-of select="#id2"/>,<xsl:text/>
<xsl:value-of select="#content"/>,<xsl:text/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
EDIT: Another alternative that uses the template match of the root node and does not need to know what the document element is:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:text>id2,content,
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="DEVICEMESSAGES/HEADER">
<xsl:value-of select="#id2"/>,<xsl:text/>
<xsl:value-of select="#content"/>,<xsl:text/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>