XSLT执行存储在变量中的xpath列表

时间:2017-01-15 14:47:55

标签: xml xslt xpath

我正在尝试使用XSLT 1.0执行一组存储在变量中的给定xpath。在模板中使用for-each访问xpath列表时,上下文会发生变化,因此无法从原始xml中提取任何xpath值。它只返回空值。

输入xml:

<catalog>
    <book id="bk101">
        <author>Gambardella Matthew</author>
        <title>XML Developer's Guide</title>
        <genre>Computer</genre>
        <price>44.95</price>
        <publish_date>2000-10-01</publish_date>
    </book>
    <book id="bk102">
        <author>Ralls Kim</author>
        <title>Midnight Rain</title>
        <genre>Fantasy</genre>
        <price>5.95</price>
    </book>
</catalog>

XSLT我试过了:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dyn="http://exslt.org/dynamic" xmlns:exsl="http://exslt.org/common" version="1.0" exclude-result-prefixes="dyn exsl">
  <xsl:variable name="newLine" select="'&#xA;'" />
  <xsl:variable name="comma" select="','" />
  <xsl:variable name="details">
    <xpaths>
      <xpath>/catalog/book/author</xpath>
      <xpath>/catalog/book/title</xpath>
      <xpath>/catalog/book/genre</xpath>
      <xpath>/catalog/book/price</xpath>
      <xpath>/catalog/book/publish_date</xpath>
    </xpaths>
  </xsl:variable>
  <xsl:template match="/">
    <xsl:apply-templates select="*" mode="extract" />
  </xsl:template>
  <xsl:template match="book" mode="extract">
    <xsl:if test="position() !=1">
      <xsl:value-of select="$newLine" />
    </xsl:if>
    <xsl:for-each select="exsl:node-set($details)/xpaths/xpath">
      <xsl:if test="position() ! =1" />
      <xsl:value-of select="$comma" />
      <xsl:variable name="this" select="." />
      <xsl:value-of select="dyn:evaluate($this)" />
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

我期待的输出是:

Gambardella Matthew,XML Developer's Guide,Computer,44.95,2000-10-01
Ralls Kim,Midnight Rain,Fantasy,5.95,,

xslt以上的输出产生:

,,,,,
,,,,,

有人可以提供所需的XSLT 1.0的线索吗?提前谢谢。

1 个答案:

答案 0 :(得分:1)

我不认为您使用的绝对XPath表达式在book元素的上下文中有意义,您需要使用相对路径。然后,您可以按如下方式更改本书的上下文:

<xsl:variable name="details">
    <xpaths>
        <xpath>author</xpath>
        <xpath>title</xpath>
        <xpath>genre</xpath>
        <xpath>price</xpath>
        <xpath>publish_date</xpath>
    </xpaths>
</xsl:variable>
<xsl:template match="/">
    <xsl:apply-templates select="*" mode="extract" />
</xsl:template>
<xsl:template match="book" mode="extract">
    <xsl:if test="position() !=1">
        <xsl:value-of select="$newLine" />
    </xsl:if>
    <xsl:variable name="book" select="."/>
    <xsl:for-each select="exsl:node-set($details)/xpaths/xpath">
        <xsl:if test="position() != 1">
            <xsl:value-of select="$comma" />
        </xsl:if>
        <xsl:variable name="path" select="." />
        <xsl:for-each select="$book"><xsl:value-of select="dyn:evaluate($path)" /></xsl:for-each>
    </xsl:for-each>
</xsl:template>

显然,如果您只是使用$book/*[local-name() = $path],则可以在不使用通常不受支持的dyn:evaluate的情况下使其工作。