我仍然在使用XSLT,但我在使用XSLT模板时遇到了麻烦。我正在尝试创建一个模板来匹配我的XML数据的每个缩进级别,但出于某种原因,无论我尝试的apply-templates调用的变体是什么,我只能打印第一个缩进级别..或者更确切地说,它只应用一个缩进级别,就好像它匹配出现的第一个模式而忽略其余的模式。有人可以告诉我的XSLT语法有什么不对吗?同样的方法用于其他一些数据,并且工作正常。
<?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 all elements within the 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 a tag containing the name of the 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 a tag containing the name of the 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>
不幸的是,我无法发布样本数据,但格式就是这样。
<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>
当我只留下第一个apply-templates调用时,它给了我第一层,我应该期待的,这是所有第一层属性标签......但如果我放入下一行,哪个应该匹配模板#2,它只是在模板1的模式后面打印完全相同的数据,而不是匹配模板2的模式数据。为什么忽略我的其他模板?
答案 0 :(得分:2)
您的XSLT无效 - apply-templates
具有select
属性,而不是match
属性。一旦修复,它会产生以下结果:
<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>
正如您在此处所见,您的第二个模板正在使用。 <element2>
有8个实例。也许你没有注意到它们,因为它们发生在所有<element>
之后。所有<elements>
首先出现的原因是您首先将模板应用于所有第一级<Property>
节点,然后将模板应用到下一级别。如果您希望每个节点的子节点都列在父节点之后,您应该像这样编写XSLT:
<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 all elements within the 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 a tag containing the name of the 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 a tag containing the name of the 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>
注意我是如何在6个模板的末尾添加<xsl:apply-templates select="*" />
的。我认为还有其他方法可以改进这个XSLT,但由于它似乎只是一个样本,我将把它留给另一个问题。
我认为你的逻辑在这里也被打破了:
<xsl:for-each select="../../*[1]">
在这里:
<xsl:for-each select="../../../../*[1]">
如果要切换到父母和祖父母的上下文,则应使用:
<xsl:for-each select="..">
和
<xsl:for-each select="../..">