【问题标题】:XSLT param identity transform without input XML没有输入 XML 的 XSLT 参数身份转换
【发布时间】:2014-12-09 10:16:38
【问题描述】:

我尝试了几天,但没有成功。我有以下 XSLT,它不接受任何输入 XML,但有一个参数作为 XML:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:param name="products">
        <products author="Jesper">
            <product id="p1">
                <name>Delta</name>
                <price>800</price>
                <stock>4</stock>
                <country>Denmark</country>
            </product>
            <product id="p2">
                <name>Golf</name>
                <price>1000</price>
                <stock>5</stock>
                <country>Germany</country>
            </product>
            <product id="p3">
                <name>Alfa</name>
                <price>1200</price>
                <stock>19</stock>
                <country>Germany</country>
            </product>
            <product id="p4">
                <name>Foxtrot</name>
                <price>1500</price>
                <stock>5</stock>
                <country>Australia</country>
            </product>
            <!-- p5 is a brand new product -->
            <product id="p5">
                <name>Tango</name>
                <price>1225</price>
                <stock>3</stock>
                <country>Japan</country>
            </product>
        </products>
    </xsl:param>
    <xsl:template match="@*|node()" name="initial">
        <xsl:copy>
            <xsl:apply-templates select="$products / @*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="products">
        <xsl:copy>
            <xsl:attribute name="dateUpdated">
      <xsl:value-of select="current-dateTime()" />
    </xsl:attribute>
            <xsl:apply-templates select="$products / @*|node()" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

这是来自here 的示例,我只是使用输入 XML 作为参数。 我的问题是如何在 XSLT 参数上进行身份转换并使这种转换工作?

【问题讨论】:

  • 这个参数是硬编码到你的样式表中的吗?如果是,为什么需要转换它(在同一个样式表中)?
  • 它实际上是作为外部参数来的,这只是一个例子,这样更容易测试
  • 是的,如果它作为参数出现,那么它作为字符串出现,而不是作为 XML。我从您的另一个问题中了解到您已经意识到这一点,但是这个问题本身并没有什么意义。也许将文件的路径作为参数传递会更好?
  • 还要注意,在这个特定的例子中,复制比恒等变换更合适。

标签: xml xslt params


【解决方案1】:

进行以下更改以使您的 XSLT 2.0 转换工作:

  1. as="node()" 添加到xsl:param
  2. 匹配(忽略的)输入 XML 的根元素和 &lt;xsl:apply-templates select="$products"/&gt; 从那里得到 从参数 XML 开始。
  3. 从您其他人的xs:apply-templates 中删除$products 模板。
  4. 从您的身份模板中删除 name="initial"

然后,您的 XSLT 2.0 转换与上述更新:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:param name="products" as="node()">
    <products author="Jesper">
      <product id="p1">
        <name>Delta</name>
        <price>800</price>
        <stock>4</stock>
        <country>Denmark</country>
      </product>
      <product id="p2">
        <name>Golf</name>
        <price>1000</price>
        <stock>5</stock>
        <country>Germany</country>
      </product>
      <product id="p3">
        <name>Alfa</name>
        <price>1200</price>
        <stock>19</stock>
        <country>Germany</country>
      </product>
      <product id="p4">
        <name>Foxtrot</name>
        <price>1500</price>
        <stock>5</stock>
        <country>Australia</country>
      </product>
      <!-- p5 is a brand new product -->
      <product id="p5">
        <name>Tango</name>
        <price>1225</price>
        <stock>3</stock>
        <country>Japan</country>
      </product>
    </products>
  </xsl:param>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="products">
    <xsl:copy>
      <xsl:attribute name="dateUpdated">
        <xsl:value-of select="current-dateTime()" />
      </xsl:attribute>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/">
    <xsl:apply-templates select="$products"/>
  </xsl:template>
</xsl:stylesheet>

将产生所需的输出 XML:

<?xml version="1.0" encoding="UTF-8"?>
<products dateUpdated="2014-12-09T06:38:15.8-05:00" author="Jesper">
   <product id="p1">
      <name>Delta</name>
      <price>800</price>
      <stock>4</stock>
      <country>Denmark</country>
   </product>
   <product id="p2">
      <name>Golf</name>
      <price>1000</price>
      <stock>5</stock>
      <country>Germany</country>
   </product>
   <product id="p3">
      <name>Alfa</name>
      <price>1200</price>
      <stock>19</stock>
      <country>Germany</country>
   </product>
   <product id="p4">
      <name>Foxtrot</name>
      <price>1500</price>
      <stock>5</stock>
      <country>Australia</country>
   </product>
   <product id="p5">
      <name>Tango</name>
      <price>1225</price>
      <stock>3</stock>
      <country>Japan</country>
   </product>
</products>

XSLT 1.0 解决方案

OP 的转换被声明为使用 XSLT 2.0,但对于以后想要在 XSLT 1.0 中执行此操作的任何人,可以通过document('')

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:param name="products">
    <products author="Jesper">
      <product id="p1">
        <name>Delta</name>
        <price>800</price>
        <stock>4</stock>
        <country>Denmark</country>
      </product>
      <product id="p2">
        <name>Golf</name>
        <price>1000</price>
        <stock>5</stock>
        <country>Germany</country>
      </product>
      <product id="p3">
        <name>Alfa</name>
        <price>1200</price>
        <stock>19</stock>
        <country>Germany</country>
      </product>
      <product id="p4">
        <name>Foxtrot</name>
        <price>1500</price>
        <stock>5</stock>
        <country>Australia</country>
      </product>
      <!-- p5 is a brand new product -->
      <product id="p5">
        <name>Tango</name>
        <price>1225</price>
        <stock>3</stock>
        <country>Japan</country>
      </product>
    </products>
  </xsl:param>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="products">
    <xsl:copy>
      <xsl:attribute name="dateUpdated">
        <xsl:value-of select="current-dateTime()" />
      </xsl:attribute>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/">
    <xsl:apply-templates select="document('')//xsl:param[@name='products']/products"/>
  </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 您还可以通过调用命名模板来运行 XSLT 2.0 转换,而不必传入虚拟 XML 文档。
  • 我就是这样做的,这就是为什么我有 name="initial"
  • 你能看看这个问题吗,这是我的真实用例:stackoverflow.com/questions/27379248/…
  • 如果您愿意,您仍然可以将name="initial" 移至新的&lt;xsl:template match="/"&gt;
猜你喜欢
  • 1970-01-01
  • 2017-12-29
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多