Reputation: 167
I am playing around with XSLT for a small task. I have the following XML:
<PFeed>
<PID> MyProcess </PID>
<Version>1</Version>
<MetaData>
<Id> MyMetadataId </Id>
</MetaData>
<AllFeeds>
<FeedContent>
<Id> FeedContentId </Id>
</FeedContent>
</AllFeeds>
</PFeed>
I want to extract FeedContentId
as text from this XML.
This is the XSLT code I have:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/PFeed/AllFeeds/FeedContent">
<xsl:value-of select="Id"/>
</xsl:template>
</xsl:stylesheet>
But instead of outputting FeedContentId
I get the following:
MyProcess 1 MyMetadataId FeedContentId
Can you please point out what I am missing ?
Upvotes: 3
Views: 47
Reputation: 22647
The output of your current XSLT code is:
MyProcess 1 MyMetadataId FeedContentId
which is all the text inside the input XML document. This is because there is only one template in your stylesheet, and it does not apply to everything in the input document. For a part of the input, the XSLT processor has to resort to predefined default templates.
The default template for elements skips elements, the default template for text nodes copies those text nodes, and that's exactly what happens.
A solutions is to directly target the content you are interested in (/PFeed/AllFeeds/FeedContent/Id
) with one template and write another template that matches text nodes:
<xsl:template match="text()"/>
to override the default behaviour for text nodes.
Also, if your output format is plain text, you should use
<xsl:output method="text"/>
and possibly get rid of extra spaces:
<xsl:strip-space elements="*"/>
XSLT Stylesheet
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/PFeed/AllFeeds/FeedContent/Id">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
Text Output
FeedContentId
Try this solution online here.
Upvotes: 1
Reputation: 5353
You first need a template to match the root element, then match what's inside. This XSLT now works again. (Test e.g. on http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog)
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/PFeed">
<xsl:apply-templates select="AllFeeds/FeedContent"/>
</xsl:template>
<xsl:template match="FeedContent">
<xsl:value-of select="Id"/>
</xsl:template>
</xsl:stylesheet>
Output after transformation:
FeedContentId
However, the same thing (getting the /PFeed/AllFeeds/FeedContent/Id
node) could also be achieved by evaluating the above simple XPath expression.
Upvotes: 2