2011-08-08 33 views
1

我正在寻找将参数传递给模板匹配的解决方法。我知道这在XPath中是不允许的,因此我正在寻找一个'B计划'解决方案。如何模仿与参数值调用模板匹配?

这就是我想会的工作:

XSLT的第1部分(2.0):

<xsl:template match="/"> 
    <xsl:for-each select="//Main/PageList/Page"> 
    <xsl:result-document href="{@ID}.xml"> 
     <Page ID="{@ID}"> 
      <xsl:apply-templates select="node()"> 
       <xsl:with-param name="theID" select="@ID"/> 
      </xsl:apply-templates> 
     </Page> 
    </xsl:result-document> 
    </xsl:for-each> 
</xsl:template> 

所以相当简单,不用理会使用的标记,它的作用在本质上是通过一个节点,并为每个节点创建一个单一的XML文件。每个节点都以一个ID开头,这是我希望为其他模板提供的这个ID。不幸的是这工作正常进行命名模板,但它并不适用于那些匹配工作(如果我理解正确的理论至少)

所以下面是我想看到的是什么工作:

<!-- identity template --> 
    <xsl:template match="node()|@*"> 
    <xsl:param name="theID"/> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"> 
      <xsl:with-param name="theID" select="$theID"/> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

<!-- lots of templates here doing what I want them to do --> 

<!-- one template creating an issue --> 

<xsl:template match="@src"> 
<!-- would be nice to know the current ID, but unfortunately this one stays empty... --> 
<xsl:param name="theID"/> 

<!-- clean current attribute a bit --> 
<xsl:variable name="S1" select="replace(.,'\.\.\/','')"/> 

<xsl:attribute name="src"> 
<xsl:choose> 
<xsl:when test="contains($S1,'common')"> 
<!-- just use current value, don't bother about current ID --> 
    <xsl:value-of select="$S1"/> 
</xsl:when> 
<xsl:otherwise> 
    <!-- use ID parameter --> 
    <xsl:value-of select="concat($theID,'_',$S1)"/> 
</xsl:otherwise> 
</xsl:choose> 
</xsl:attribute> 
</xsl:template> 

不要看代码,它只是整个文件的一小部分,但其实质是我想从我的第一部分(match =“/”)使用其他模板中的ID参数(match = “@src”),但这似乎相当复杂。

我错过了什么吗?如果我只是运气不好而且确实不可能,那么有没有人会有建议,我可以怎么做?

在此先感谢!

+0

您可以通过这种方式将params传递给模板匹配。可能将模板应用于node()过于泛型,并且会在没有参数的情况下匹配模板。 –

+0

@empo:我试过去除node()部分,但没有真正的区别(尽管可能误解了你的观点,所以不确定这是你的目标)。 'match'部分的参数仍然是空的,所以如果它能工作的话,我确实在这个过程中的某处丢失了它。我会玩一个简单的版本(我目前的XSLT稍微复杂一点,然后提供简化) – Wokoman

+0

我的意思是你可能需要'xsl:apply-templates select =“// @ src”'where @src代替node()。 –

回答

1

你的问题是在这里

<xsl:apply-templates select="node()"> 
    <xsl:with-param name="theID" select="@ID"/> 
</xsl:apply-templates> 

select属性指定的处理应继续对当前节点的任何孩子节点。

但是node()只选择儿童节点(元素,文本节点,处理指令和注释) - 不属性

  1. 为了直接引起(全部)的处理属性的当前节点的,使用:

-

<xsl:apply-templates select="@*"> 
    <xsl:with-param name="theID" select="@ID"/> 
</xsl:apply-templates> 

。 2。 为了使仅当前节点使用的src属性处理:

-

<xsl:apply-templates select="@src"> 
    <xsl:with-param name="theID" select="@ID"/> 
</xsl:apply-templates> 

0.3。为了间接进程属性TOF当前节点的后代,这样做:

-

<xsl:apply-templates select="node()|@*"> 
    <xsl:with-param name="theID" select="@ID"/> 
</xsl:apply-templates> 

您还必须确保处理node()任何模板必须有一个名为xsl:paramtheID它必须在任何xsl:apply-templates指令中传递此参数。

实际上,这意味着您会覆盖所有XSLT内置模板,因为他们不知道您的xsl:param

+0

我应该已经更清楚了,但实际上有很多模板,所以直接调用src并不会做到这一点(实际上src是img元素的一部分,它正在做什么......)我通过阅读你的反馈是我的参数在第一次传递后丢失了,所以我认为它很聪明,并将其添加到身份模板(我修改了我的问题),但这也没有帮助。那么,我在这里忽略了哪些明显的部分? (在我的主模板中更改为node()| attr *没有什么区别,实际上我忽略了开始时的属性) – Wokoman

+0

@Wokoman:必须将“xsl:param”添加到所有模板,并且所有模板都应该将'xsl:with-param'传递给他们正在应用的模板(使用'xsl:apply-templates')。仅仅声明'xsl:param'是不够的,它也应该被传递给正在被应用的模板。 –

+0

好吧,害怕那样:-)只是为了我的兴趣(并且为了让我学习饥饿......)为什么它不足以将其应用于身份模板?我一直认为这将通过级联。如果太复杂太解释不要打扰,如前所述,这只是为了更好地理解,以便将来避免这些问题。 – Wokoman

0

我想,而不是

 <xsl:apply-templates select="node()"> 
      <xsl:with-param name="theID" select="@ID"/> 
     </xsl:apply-templates> 

您更希望

 <xsl:apply-templates select="node()"> 
      <xsl:with-param name="theID" select="parent::Page/@ID"/> 
     </xsl:apply-templates> 

假设你想通过父Page元素的ID属性。

另一方面select="node()"选择像子元素,子注释节点,子文本节点,子处理指令节点的任何子节点,所以我不明白为什么您以后显示匹配属性节点的模板。

+0

我只显示了一个模板,但实际上有几十个,并且都对主数据进行了一些重构(逐页)。我在这里提到的具体问题的问题是我需要重建一个图像的路径,并且有两种类型的路径。对于一个我可以保留的价值,但对于其他人我需要有当前页(ID),以允许重建实际路径。我知道我听起来非常复杂,但比描述更容易看出来(非母语人士也没有帮助......)。不幸的是,使用你的改变并没有改变。 – Wokoman