xslt copy-of without children
hi i have a sitemap xml document that looks something like this
<pagenode title="home" url="~/" fornavbar="true">
<pagenode title="admin" url="~/admin" fornavbar="false">
<pagenode title="users" url="~/admin/users" fornavbar="false"/>
<pagenode title="events" url="~/admin/events" fornavbar="true"/>
</pagenode>
<pagenode title="catalog" url="~/catalog" fornavbar="true"/>
<pagenode title="contact us" url="~/contactus" fornavbar="false"/>
</pagenode>
now i want to retrieve an xml document for the navbar, which includes all the pagenodes that have fornavbar=true. how can this be done?
the closest i was able to get so far was this:
<?xml v开发者_高级运维ersion="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="pagenode[@fornavbar='true']">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
the problem with this is that includes all the children of anything matched as navbar
i only want to copy all the attributes, not all the children
but if i try
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="pagenode[@fornavbar='true']">
<pagenode title="{@title}" url="{@url}"/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
then i have 2 problems
- i might type out each attribute separately, and i have quite a few per page and theyre apt to change eventually
- it loses the hierarchy. everything becomes flat one after the other
i would appreciate all and any help in the matter.
thank you!
EDIT: sample output that id like to see
<pagenode title="home" url="~/" fornavbar="true">
<pagenode title="events" url="~/admin/events" fornavbar="true"/>
<pagenode title="catalog" url="~/catalog" fornavbar="true"/>
</pagenode>
you can iterate over the attributes of an node using xsl:foreach select="@*"
this way you don't have to copy the attributes by hand. if you call xsl:apply-templates
inside of yor pagenode element you should get the desired result.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="pagenode[@fornavbar='true']">
<pagenode>
<xsl:for-each select="@*">
<xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute>
</xsl:for-each>
<xsl:apply-templates/>
</pagenode>
</xsl:template>
</xsl:stylesheet>
makes
<?xml version="1.0"?>
<pagenode title="home" url="~/" fornavbar="true">
<pagenode title="events" url="~/admin/events" fornavbar="true"/>
<pagenode title="catalog" url="~/catalog" fornavbar="true"/>
</pagenode>
This is probably the shortest and purest XSLT solution:
<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="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@fornavbar = 'false']">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<pagenode title="home" url="~/" fornavbar="true">
<pagenode title="admin" url="~/admin" fornavbar="false">
<pagenode title="users" url="~/admin/users" fornavbar="false"/>
<pagenode title="events" url="~/admin/events" fornavbar="true"/>
</pagenode>
<pagenode title="catalog" url="~/catalog" fornavbar="true"/>
<pagenode title="contact us" url="~/contactus" fornavbar="false"/>
</pagenode>
the wanted, correct result is produced:
<pagenode title="home" url="~/" fornavbar="true">
<pagenode title="events" url="~/admin/events" fornavbar="true"/>
<pagenode title="catalog" url="~/catalog" fornavbar="true"/>
</pagenode>
Explanation:
The identity rule (template) copies every node "as-is". Using the identity rule and overriding it is the most fundamental XSLT design pattern.
There is a single template that overrides the identity rule -- for elements whose
fornavbar
attribute is"false"
. Here the specified action is to apply-templates on the children of the current element.
XSLT should look like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="pagenode[@fornavbar='true']">
<pagenode>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</pagenode>
</xsl:template>
</xsl:stylesheet>
精彩评论