xml - XSLT Only One Template Matching? -
i'm still wet behind ears xslt, , i'm having problem xslt templates. i'm trying create template match each indentation level of xml data, reason, no matter variation of apply-templates calls try, i'm able print first indentation level... or rather, it's applying 1 indentation level, if it's matching first pattern comes , ignoring rest. can tell if off xslt syntax? same method used other data, , worked fine.
<?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" omit-xml-declaration="no" indent="yes" /> <xsl:strip-space elements="*" /> <xsl:template match="/"> <config> <xsl:apply-templates match="/objects/*/*" /> <!-- matches template #1 --> <xsl:apply-templates match="/objects/*/*/*" /> <!-- matches template #2 --> <xsl:apply-templates match="/objects/*/*/*/*" /> <!-- matches template #3 --> <xsl:apply-templates match="/objects/*/*/*/*/*" /> <!-- matches template #4 --> <xsl:apply-templates match="/objects/*/*/*/*/*/*" /> <!-- matches template #5 --> <xsl:apply-templates match="/objects/*/*/*/*/*/*/*" /> <!-- matches template #6 --> </config> </xsl:template> <!-- <xsl:template match="object"> <element> <typefield>object</typefield> <xsl:call-template name="elementprinter" /> </element> </xsl:template> --> <!-- begin template #1 --> <xsl:template match="object/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="elementprinter" /> </element> </xsl:template> <!-- end template #1 --> <!-- begin template #2 --> <xsl:template match="object/*/*"> <element2> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element2> </xsl:template> <!-- end template #2 --> <!-- begin template #3 --> <xsl:template match="object/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> </xsl:template> <!-- end template #3 --> <!-- begin template #4 --> <xsl:template match="object/*/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> </xsl:template> <!-- end template #4 --> <!-- begin template #5 --> <xsl:template match="object/*/*/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> </xsl:template> <!-- end template #5 --> <!-- begin template #6 --> <xsl:template match="object/*/*/*/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> </xsl:template> <!-- end template #6 --> <!-- prints elements within matching node. --> <xsl:template name="elementprinter"> <xsl:for-each select="*"> <xsl:if test="text() != ''"> <xsl:choose> <xsl:when test="@name"> <xsl:variable name="ename"> <xsl:value-of select="@name" /> </xsl:variable> <xsl:element name="{$ename}"> <xsl:value-of select="text()" /> </xsl:element> </xsl:when> <xsl:when test="not(@name)"> <xsl:variable name="ename"> <xsl:value-of select="@type" /> </xsl:variable> <xsl:element name="{$ename}"> <xsl:value-of select="text()" /> </xsl:element> </xsl:when> </xsl:choose> </xsl:if> </xsl:for-each> </xsl:template> <!-- prints tag containing name of node's parent. --> <xsl:template name="parentidprinter"> <xsl:for-each select="../../*[1]"> <xsl:choose> <xsl:when test="./@name"> <xsl:variable name="pname"> <xsl:value-of select="@name" /> </xsl:variable> <xsl:element name="parent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:variable name="pname"> <xsl:value-of select="@type" /> </xsl:variable> <xsl:element name="parent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <!-- prints tag containing name of node's grandparent. --> <xsl:template name="gparentidprinter"> <xsl:for-each select="../../../../*[1]"> <xsl:choose> <xsl:when test="./@name"> <xsl:variable name="pname"> <xsl:value-of select="@name" /> </xsl:variable> <xsl:element name="grandparent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:variable name="pname"> <xsl:value-of select="@type" /> </xsl:variable> <xsl:element name="grandparent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> </xsl:stylesheet>
unfortunately, can't post sample data, format pretty much this.
<objects> <object> <property name="whatever"> <property name="whatever1.1">whatever</property> <property name="whatever1.2">whatever2</property> </property> <property name="whatever"> <property name="whatever1.1">whatever</property> <property name="whatever1.2">whatever2</property> </property> </object> <object> <property name="whatever"> <property name="whatever1.1">whatever</property> <property name="whatever1.2">whatever2</property> </property> <property name="whatever"> <property name="whatever1.1">whatever</property> <property name="whatever1.2">whatever2</property> </property> </object> </objects>
when leave first apply-templates phone call in, gives me first layer, should expect, first-layer property tags... if set in next line, should match template #2, print exact same info template 1's pattern right after it, instead of matching template 2's pattern data. why ignoring other templates?
your xslt invalid - apply-templates
has select
attribute, not match
attribute. 1 time fixed, produces next result:
<config> <element> <typefield>whatever</typefield> <whatever1.1>whatever</whatever1.1> <whatever1.2>whatever2</whatever1.2> </element> <element> <typefield>whatever</typefield> <whatever1.1>whatever</whatever1.1> <whatever1.2>whatever2</whatever1.2> </element> <element> <typefield>whatever</typefield> <whatever1.1>whatever</whatever1.1> <whatever1.2>whatever2</whatever1.2> </element> <element> <typefield>whatever</typefield> <whatever1.1>whatever</whatever1.1> <whatever1.2>whatever2</whatever1.2> </element> <element2> <typefield>whatever1.1</typefield> <parent>whatever</parent> </element2> <element2> <typefield>whatever1.2</typefield> <parent>whatever</parent> </element2> <element2> <typefield>whatever1.1</typefield> <parent>whatever</parent> </element2> <element2> <typefield>whatever1.2</typefield> <parent>whatever</parent> </element2> <element2> <typefield>whatever1.1</typefield> <parent>whatever</parent> </element2> <element2> <typefield>whatever1.2</typefield> <parent>whatever</parent> </element2> <element2> <typefield>whatever1.1</typefield> <parent>whatever</parent> </element2> <element2> <typefield>whatever1.2</typefield> <parent>whatever</parent> </element2> </config>
as can see here, sec template is beingness used. there 8 instances of <element2>
. perhaps didn't notice them because occur after of <element>
s. reason of <elements>
appear first apply templates of first-level <property>
nodes first, , apply templates next level. if want each node's children listed after parents, should write xslt this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" omit-xml-declaration="no" indent="yes" /> <xsl:strip-space elements="*" /> <xsl:template match="/"> <config> <xsl:apply-templates select="/objects/*/*" /> <!-- matches template #1 --> </config> </xsl:template> <!-- <xsl:template match="object"> <element> <typefield>object</typefield> <xsl:call-template name="elementprinter" /> </element> </xsl:template> --> <!-- begin template #1 --> <xsl:template match="object/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="elementprinter" /> </element> <xsl:apply-templates select="*" /> </xsl:template> <!-- end template #1 --> <!-- begin template #2 --> <xsl:template match="object/*/*"> <element2> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element2> <xsl:apply-templates select="*" /> </xsl:template> <!-- end template #2 --> <!-- begin template #3 --> <xsl:template match="object/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> <xsl:apply-templates select="*" /> </xsl:template> <!-- end template #3 --> <!-- begin template #4 --> <xsl:template match="object/*/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> <xsl:apply-templates select="*" /> </xsl:template> <!-- end template #4 --> <!-- begin template #5 --> <xsl:template match="object/*/*/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> <xsl:apply-templates select="*" /> </xsl:template> <!-- end template #5 --> <!-- begin template #6 --> <xsl:template match="object/*/*/*/*/*/*"> <element> <typefield> <xsl:value-of select="@name" /> </typefield> <xsl:call-template name="gparentidprinter" /> <xsl:call-template name="parentidprinter" /> <xsl:call-template name="elementprinter" /> </element> <xsl:apply-templates select="*" /> </xsl:template> <!-- end template #6 --> <!-- prints elements within matching node. --> <xsl:template name="elementprinter"> <xsl:for-each select="*"> <xsl:if test="text() != ''"> <xsl:choose> <xsl:when test="@name"> <xsl:variable name="ename"> <xsl:value-of select="@name" /> </xsl:variable> <xsl:element name="{$ename}"> <xsl:value-of select="text()" /> </xsl:element> </xsl:when> <xsl:when test="not(@name)"> <xsl:variable name="ename"> <xsl:value-of select="@type" /> </xsl:variable> <xsl:element name="{$ename}"> <xsl:value-of select="text()" /> </xsl:element> </xsl:when> </xsl:choose> </xsl:if> </xsl:for-each> </xsl:template> <!-- prints tag containing name of node's parent. --> <xsl:template name="parentidprinter"> <xsl:for-each select="../../*[1]"> <xsl:choose> <xsl:when test="./@name"> <xsl:variable name="pname"> <xsl:value-of select="@name" /> </xsl:variable> <xsl:element name="parent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:variable name="pname"> <xsl:value-of select="@type" /> </xsl:variable> <xsl:element name="parent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <!-- prints tag containing name of node's grandparent. --> <xsl:template name="gparentidprinter"> <xsl:for-each select="../../../../*[1]"> <xsl:choose> <xsl:when test="./@name"> <xsl:variable name="pname"> <xsl:value-of select="@name" /> </xsl:variable> <xsl:element name="grandparent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:variable name="pname"> <xsl:value-of select="@type" /> </xsl:variable> <xsl:element name="grandparent"> <xsl:value-of select="$pname" /> </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> </xsl:stylesheet>
notice how added <xsl:apply-templates select="*" />
end of 6 templates. think there other ways improve xslt, since seems sample, i'll leave question.
i think logic broken here:
<xsl:for-each select="../../*[1]">
and here:
<xsl:for-each select="../../../../*[1]">
if want switch context of parent , grandparent, should use:
<xsl:for-each select="..">
and
<xsl:for-each select="../..">
xml xslt
No comments:
Post a Comment