如何在xslt中找到从节点到其子节点的相对xpath表示法?

时间:2012-11-01 16:42:28

标签: xml xslt xpath

我对xslt比较陌生,但我有一些运气造型巨大的xml文件。现在我被困在一个地方,无法继续。可以说xml文件的结构有点像

<xxx>
.......
.......
.......
 <Field id="123" type="fld" elem="3">
   <td:value passed="true"> 25 </td:value>
 </Field>
.......
.......
.......

</xxx>

我目前在Field节点中。如果我执行<xsl:value of select="name()" />它会发出“字段”,如果我执行<xsl:value of select="@type" />,我会得到“fld”。但是,如果我执行<xsl:value of select="." />我得到<td:value>内的值为25。

我担心的是我需要在td:value中获取'passed'属性的值。如果我使用当前位置的以下模板,我可以访问该属性。

<xsl:apply-templates select="*[@passed]" />

  <xsl:template match="*[@passed]" >
       <xsl:value-of select="@passed" />
     </xsl:template>

但问题是'pass'属性可能不会总是存在,所以我需要只使用节点名称到达<td:value>节点。

我试过

<xsl:apply-templates select=".//td" />
<xsl:apply-templates select=".//td:value" />
<xsl:apply-templates select=".//*" />
<xsl:apply-templates select=".*" />
<xsl:apply-templates select="td" />
似乎什么都没有用。如何从Field节点获取该td:value节点?

2 个答案:

答案 0 :(得分:2)

您需要在输入XML中声明分配给td前缀td:value的相同名称空间。例如:

<foo xmlns:td="urn:td">
  <Fieldid="123" type="fld" elem="3">
    <td:value passed="true"> 25 </td:value>
  </Field>
</foo>

XSLT可能类似于:

<xsl:template match="Field">
  <xsl:if test="td:value@passed" xmlns:td="urn:td">
    <xsl:value-of select="td:value"/>
  </xsl:if>
</xsl:template>

重要的是,命名空间与输入文档中的命名空间相同,如果XSLT文档中的前缀命名不同,则无关紧要。如果可能,并且所有XML都在您的控制之下,为了清楚起见,它应该是。

答案 1 :(得分:1)

为了澄清一下,您目前定位于字段元素,并且您尝试选择子 td:value 以获取其 @passed < / strong>属性,但如果此属性不存在,则需要获取元素的值。

嗯,你能做的就是先做,就是替换这个

<xsl:apply-templates select="*[@passed]" />

只有这个

<xsl:apply-templates select="*" />

然后,您需要两个匹配的模板;一个用于存在属性,一个用于捕获其他情况

<xsl:template match="Field/*[@passed]" >
   <xsl:value-of select="@passed" />
</xsl:template>

<xsl:template match="Field/*" >
   <xsl:value-of select="." />
</xsl:template>

当您有两个这样的模板时,XSLT将首先匹配更具体的模板。因此,如果存在 @passed 属性,则第一个模板将始终匹配(即使第二个模板也匹配它)。当没有一个存在时,将使用第二个。

编辑:如果您不想指定元素名称,可以用这个替换模板...

<xsl:template match="*[@passed]" >
   <xsl:value-of select="@passed" />
</xsl:template>

<xsl:template match="*" >
   <xsl:value-of select="." />
</xsl:template>

但是,这些将开始匹配可能影响XSLT其他部分的所有元素。因此,您可能必须使用模式参数

<xsl:apply-templates select="*" mode="Field" />

<xsl:template match="*[@passed]" mode="Field" >
   <xsl:value-of select="@passed" />
</xsl:template>

<xsl:template match="*" mode="Field" >
   <xsl:value-of select="." />
</xsl:template>