【问题标题】:Conversion from XSLT 1.0 to 2.0 doesn't give first text from a tag从 XSLT 1.0 到 2.0 的转换不会给出标签的第一个文本
【发布时间】:2016-06-29 15:04:02
【问题描述】:

我正在尝试使用 XSLT 2.0,但是标签 <xsl:value-of select=...> 不再给我第一个元素。我得到了 XML 中的所有值。如何将以下 XSLT 转换为与 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:template match="Data">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="Data/ABC">
        <xsl:for-each select=".">
            <Data xmlns="example.com">
                <GEF>
                    <id><xsl:value-of select="id"/></id>
                    <time><xsl:value-of select="time"/></time>
                    <type>test</type>
                </GEF>
            </Data>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

如果我有这个 XML:

<Data xmlns="example.com">
    <ABC>
        <id>2</id>
        <time>125622</time>
    </ABC>
</Data>

如果我使用的是 XSLT 1.0,我会得到这个:

<Data xmlns="example.com">
    <GEF>
        <id>2</id>
        <time>125622</time>
        <type>test</type>
    </GEF>
</Data>

通常,我会将 2125622 作为 XSLT 中每个标记的单个项目。但是,现在它只获取两个值并输出它们。转换后它甚至不打印标签。我想在 2.0 中使用什么?我的搜索没有找到任何东西。

这是我在 2.0 中得到的:

<Data xmlns="example.com">

  2
  125622
  test

</Data>

【问题讨论】:

  • 你想得到什么结果? -- 为什么你有&lt;xsl:apply-templates mode="DataRsp"/&gt; 但在那个模式下没有模板?
  • “现在它只获取两个值并输出它们。转换后它甚至不打印标签”听起来好像输入 XML 中的元素位于命名空间中,因此您的模板不适用。 Data 元素上是否有任何 xmlns="..." 或祖先?
  • 你的第二个模板匹配应该是match="ABC"。因为您对匹配进行了过度限定,所以只应用了默认的转换规则,即只发出元素的文本。删除Data/,它应该可以工作。
  • 抱歉,误删了命名空间。 @michael.hor257k 我确实有一个模板,只是没有粘贴它。我将编辑 OP。
  • 您是如何使用 XSLT 1.0 运行 XSLT 的?你有没有机会构建一个不知道命名空间的 DOM 树,而处理器因此忽略了xmlns="example.com"

标签: xml xslt saxon


【解决方案1】:

让您的代码在 XSLT 2.0 下工作的一种方法是在向后兼容模式下运行它,您只需将版本号保留为 version="1.0" 即可。如果您知道对 XSLT 1.0 语义的依赖仅适用于样式表的特定部分,那么您可以有选择地执行此操作,例如

         <xsl:for-each select="." version="1.0">
            <Data xmlns="example.com">
                <GEF>
                    <id><xsl:value-of select="id"/></id>
                    <time><xsl:value-of select="time"/></time>
                    <type>test</type>
                </GEF>
            </Data>
        </xsl:for-each>

但是,如果可以,最好将代码转换为以 2.0 方式工作。如果只希望xsl:value-of 指令处理节点集中的第一项,只需添加[1] 以选择第一项,例如

<id><xsl:value-of select="id[1]"/></id>

【讨论】:

  • 谢谢!很高兴知道我也可以这样做。
【解决方案2】:

XSLT 和 XPath(1.0 为更高版本)使用命名空间感知数据模型,因此给定 &lt;Data xmlns="example.com"&gt; Data 元素及其后代位于命名空间 example.com 中,您的 XSLT 需要考虑到这一点。在 XSLT 2.0 中,您可以使用

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xpath-default-namespace="example.com">

至于您的 Java 代码,请确保使用 namespace aware DocumentBuilderFactory

【讨论】:

  • 谢谢。我有点得到我想要的输出。它现在打印它应该如何。但是,在最后一个&lt;/Data&gt; 下,它也会打印出所有文本值。此外,&lt;xsl:param name="sheet-uri" select="some.xml"/&gt; &lt;xsl:param name="sheet-doc" select="document($sheet-uri)"/&gt; 不再工作(与 1.0 一起工作正常)。知道为什么会这样吗?再次非常感谢您的帮助!
  • 至于打印出来的文本值,我希望在使用模式但在该模式下没有任何显式模板的代码的第一个版本中会发生这种情况。对于参数问题,我认为您应该提出一个新问题,&lt;xsl:param name="sheet-uri" select="some.xml"/&gt; 肯定看起来不对,需要为&lt;xsl:param name="sheet-uri" select="'some.xml'"/&gt;。但是相对 URI 可能是个问题,请提出一个新问题,其中包含 XSLT 和 Java 代码的所有必要细节。
  • 我确实为我在 XSLT 中列出的模式定义了模板。因此,没有不使用的模式。是因为这行:``?思想用于没有模式的模板。我会为另一个问题提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 2012-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多