Reputation: 11737
I'm retrieving data from xml file and storing it in a text file. Following is the my.xml file:
<?xml version="1.0"?>
<Parent>
<Action>POSTACTION</ActionState>
<Message><![CDATA[An Exception is thrown testFunctionAlpha()]]></Message>
<Property key="Direction" value="IN"/>
<Property key="MethodName" value="testFunctionAlpha"/>
<Property key="ReturnValue" value="exception"/>
</Parent>
<Parent>
<Action>PREACTION</ActionState>
<Message><![CDATA[This is message of myFunction ]]></Message>
<Property key="Direction" value="IN"/>
<Property key="MethodName" value="myFunction"/>
<Property key="ReturnValue" value="cmy::returnvalue"/>
</Parent>
There are multiple such records in xml file. I'm using following command to parce this xml and store the date in test file.
xsltproc scan.xsl my.xml >> output.txt
Following is the scan.xsl file content used to parce xml file:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="Parent">
<xsl:variable name="mesg" select="./Message"/>
<xsl:if test="$mesg = 'An Exception is thrown testFunctionAlpha()'">
<xsl:value-of select="./Action"/><xsl:text> </xsl:text>
<xsl:value-of select="$mesg"/><xsl:text> </xsl:text>
<xsl:apply-templates select="Property[@key='Direction']"/><xsl:text> </xsl:text>
<xsl:apply-templates select="Property[@key='MethodName']"/><xsl:text> </xsl:text>
<xsl:apply-templates select="Property[@key='ReturnValue']"/>
</xsl:if>
</xsl:template>
<xsl:template match="Property"><xsl:value-of select="@value"/></xsl:template>
</xsl:stylesheet>
I want to store the date in text file only those tags having tag value is "An Exception is thrown testFunctionAlpha()" I'm able to get this using above code, but Output.txt contains, - Empty lines for the un-matched tags. How to avoid that empty lines? So that output.txt contains only data that matches xsl format.
Upvotes: 1
Views: 1504
Reputation: 107277
You can ensure that the built-in default processing templates aren't applied if you ensure that you capture the root element on your first template, and thereafter only apply templates to the elements that you want mapped.
Also, another source of newlines could be if any of your text()
s have additional whitespace in them, you can use the normalize-space()
function to trim this out in your xsl:selects
Since your example input xml isn't valid, I added a wrapper root element (xml) and changed the ActionResult
closing tag to Action
.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/xml">
<xsl:apply-templates select="Parent"/>
</xsl:template>
<xsl:template match="Parent">
<xsl:variable name="mesg" select="Message"/>
<xsl:if test="$mesg = 'An Exception is thrown testFunctionAlpha()'">
<xsl:value-of select="Action"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$mesg"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="Property[@key='Direction']"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="Property[@key='MethodName']"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="Property[@key='ReturnValue']"/>
</xsl:if>
</xsl:template>
<xsl:template match="Property">
<xsl:value-of select="@value"/>
</xsl:template>
</xsl:stylesheet>
Input XML:
<xml>
<Parent>
<Action>POSTACTION</Action>
<Message><![CDATA[An Exception is thrown testFunctionAlpha()]]></Message>
<Property key="Direction" value="IN"/>
<Property key="MethodName" value="testFunctionAlpha"/>
<Property key="ReturnValue" value="exception"/>
</Parent>
<Parent>
<Action>PREACTION</Action>
<Message><![CDATA[This is message of myFunction ]]></Message>
<Property key="Direction" value="IN"/>
<Property key="MethodName" value="myFunction"/>
<Property key="ReturnValue" value="cmy::returnvalue"/>
</Parent>
</xml>
Result:
POSTACTION An Exception is thrown testFunctionAlpha() IN testFunctionAlpha exception
Edit
If you don't want to capture the root, you can also override just the text()
built in template, by suppressing it:
<xsl:template match="text()"/>
Upvotes: 2