xml - XSLT 1.0 可以在 select 子句中的 xmlns 属性上使用变量吗?

标签 xml variables xslt namespaces xslt-1.0

我试图了解 XSLT 是否可行 1.0 脚本可与具有相似但不相等模式的 xml 文件重用,这些模式共享相同的命名空间前缀。

变量 ns-uri包含所需的 namespace ,但 XSLT 1.0 似乎无法识别 xmlns:emp='$ns-uri' 中的这种用法。尽管使用具有命名空间的字符串使用相同的属性是有效的。

我不想听从使用结构的建议 *[name()='emp:department']因为这会使 xslt 完全不可读。

还有更多建议还是这是对 XSLT 1.0 的最终限制?

注意:当我使用前缀时,How to automatically propagate the XMLNS attribute from on XSL template to another 中的答案请勿应用。

谢谢。

示例代码

以下工作:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text"/>

    <xsl:param name="ns-uri" select="/child::*[1]/namespace-uri()"/>

    <xsl:template match="emp:employee" xmlns:emp="http://www.example.com/ns/employee/2006">
        First Name "<xsl:value-of select="emp:first" xmlns:emp="http://www.example.com/ns/employee/2006"/>"
        Last Name  "<xsl:value-of select="emp:last"  xmlns:emp='$ns-uri'/>"
        Department "<xsl:value-of select="*[name()='emp:department']"/>"
    </xsl:template>
</xsl:stylesheet>

我使用这些 xml 文件作为示例(来自 Finnbarr P. Murphy's "XSLT 1.0 Multiple Namespace Issues" 中的示例)

样本1.xml:
<?xml version="1.0"?>
<emp:root xmlns:emp="http://www.example.com/ns/employee/2006">
    <emp:employee status="Guru">
        <emp:first>John</emp:first>
        <emp:last>Kane</emp:last>
        <emp:department>IT</emp:department>
        <emp:country>IE</emp:country>
    </emp:employee>
</emp:root>

样本2.xml:
<?xml version="1.0"?>
<emp:root xmlns:emp="http://www.example.com/ns/employee/2012">
    <emp:employee status="Guru">
        <emp:first>John</emp:first>
        <emp:last>Kane</emp:last>
        <emp:department>IT</emp:department>
        <emp:country>IE</emp:country>
    </emp:employee>
</emp:root>

在这两种情况下,所需的结果都应该是:
First Name "John"
Last Name  "Kane"
Department "IT"

最佳答案

您目睹的问题是由不同的命名空间引起的:

  • sample1.xml 定义 emp命名空间为 "xmlns:emp="http://www.example.com/ns/employee/2006"
  • sample2.xml 定义 emp命名空间为 "xmlns:emp="http://www.example.com/ns/employee/2012"

  • 所以在一种情况下你的模板会失败,因为它的 <template...>由于不同的命名空间前缀 ( ...2006 != ...2012 ),s 规则将不匹配。

    因此,要创建忽略 namespace 的模板,必须忽略 namespace 前缀。
    这仅通过关于 local-name() 来完成元素的名称而不是整个名称。

    例如,命名空间元素的名称可能是 emp:first .
    所以name()会返回 emp:firstlocal-name()只会返回 first .

    忽略命名空间前缀(在本例中为 emp )是通过只关注 local-name() 来实现的。所有相关元素。

    所以下面的模板是由
  • 使用 * 选择所有元素
  • 并通过使用谓词 [local-name() = '...'] 来限制这组元素它检查 local-name() 的元素匹配

  • 整个模板看起来像这样
    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
    
        <xsl:template match="*[local-name() = 'employee']">
            First Name "<xsl:value-of select="*[local-name() = 'first']" />"
            Last Name  "<xsl:value-of select="*[local-name() = 'last']" />
            Department "<xsl:value-of select="*[local-name() = 'department']" />"
        </xsl:template>
    
    </xsl:stylesheet>
    

    并为两个 XML 输入文件返回相同的结果。

    关于xml - XSLT 1.0 可以在 select 子句中的 xmlns 属性上使用变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42860885/

    相关文章:

    performance - .net 中的 XSLT 转换性能

    xml - XPath:匹配多个 child 之一

    java - 程序不会打开新窗口

    variables - for 循环中的 SCSS 第 n 个子级?

    variables - 如何在vim中高亮显示c/c++文件的变量

    java - 看到 Java 程序运行时变量值发生变化吗?

    xml - VB.net XML 获取一组节点属性并按节点对它们进行分组?

    c# - MVC Model.IsValid 用于枚举

    java - 使用 XSTREAM 将 XML 解析为 ArrayList

    php - 尽管XSL样式表几乎为空,但XSLTProcessor::importStylesheet()中的PHP警告