xslt - 引用xsl:element中的文档

时间:2011-01-12 10:17:01

标签: xslt

我想在元素中的xls中引用外部xml

<xsl:element name="{document('mapping.xml', /)/mappings/column/[@id=name()]}" >

这可能吗?

更新

mapping.xml

<?xml version="1.0" encoding="UTF-8"?>
<mappings>
      <columns>
        <column id="path">path</column>
      </columns>
</mappings>

样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:dms="http://www.news.at/dms">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:variable name="Mapping" select="document('mapping.xml', /)" />

    <xsl:template match="/">
        <xsl:element name="document">
            <xsl:for-each select="document/*">

            <xsl:element name=
  "{$Mapping/mappings/columns/column[@id = name(current())]}" />


                <xsl:element name="item" >

                <xsl:attribute name="id">
                <xsl:if test="not($Mapping/mappings/columns/column[@id= name(current())])">
                    <xsl:message>Markup Error: no id attribute in <xsl:value-of select="name(current())" /></xsl:message>
               </xsl:if>        
                        <xsl:value-of select="$Mapping/mappings/columns/column[@id= name(current())]" /></xsl:attribute>
                    <xsl:value-of select="text()" />
                </xsl:element>
            </xsl:for-each>     
        </xsl:element>
    </xsl:template>


</xsl:stylesheet>

input.xml中

<?xml version="1.0" encoding="UTF-8" ?>
<document>
   <path>sdfsdfsdf</path>
</document>

谢谢!

2 个答案:

答案 0 :(得分:1)

是的,绝对的。但是,像这样:

<xsl:element name="{normalize-space(
  document('mapping.xml', /)/mappings/column[@id=name(current())]
)}" >

简单英语:这将选择<column>/mappings等于XSLT中当前元素名称的任何@id。此列的文字值将通过normalize-space()进行修整,并成为新的<xsl:element>名称。

(请注意,comumn[@id=name()]表示“@id等于其名称的任何列”,因此仅匹配<column id="column">current()函数是必需的做你想做的事。)

但是,首先将文档保存到全局变量中会有所帮助:

<!-- at the <xsl:stylesheet> level... -->
<xsl:variable name="mappings" 
  select="document('mapping.xml', /)/mappings/column" 
/>

<!-- later, anywhere... -->
<xsl:element name="{ normalize-space($mappings[@id=name(current())]) }" >

答案 1 :(得分:1)

  

我想引用外部xml   元素中的xls

<xsl:element name=
 "{document('mapping.xml', /)/mappings/column/[@id=name()]}" >

是的,name指令的<xsl:element>属性允许AVT(属性 - 值 - 模板s

提供的代码存在许多问题

  1. 您提供的代码中存在明显的语法错误

    document('mapping.xml', /)/mappings/column/[@id=name()]

  2. 不是语法上合法的XPath表达式。最后一个位置步骤缺少节点测试,只有一个谓词。

    0.2。 上述表达式中没有任何内容与原始XML文档中的当前节点相关。我猜,谓词

    [@id=name()]

    实际上应该是这样的:

    [@id=name(current())]

    所以,我的猜测是你可能想要

     <xsl:element name=
      "{document('mapping.xml', /)/mappings/column[@id=name(current())]}" >
    

    还有一个额外的第三个问题:(在OP的评论中确认是真正的问题):

    上面name属性中指定为AVT的表达式可能具有不是语法上合法的QName的字符串值。 sych非法值的示例:123A B

    在这种情况下,有不同的可能解决方案

    • 使用另一个节点的字符串值(更改XPath表达式)。
    • 将违规字符转换为允许的字符:

    ...

    concat(
           translate(substring(yourExpression,1,1), 
                     $illegalFirstCharacters, 
                     '________________'),
           translate(substring(yourExpression,2),
                     $illegalCharacters,
                     '________________')
           )
    

    其中$illegalFirstCharacters是一个变量,定义为包含可能作为第一个字符出现且不允许作为QName的第一个字符的所有可能字符

    $illegalCharacters是一个变量,定义为包含可能出现在第一个字符之后的所有可能字符,并且在第一个字符之后不允许出现在QName中。

    基本上,$illegalFirstCharacters$illegalCharacters和字符串"0123456789"的串联。

    上面translate()的最后一个参数必须足够长,以便为每个可能的非法字符容纳一个_

    使用正则表达式在XPath 2.0(XSLT 2.0)中可以更容易地表达到有效QName的转换。

    当然,这个解决方案应该谨慎行事,因为根据实际数据,可能会将包含非法QNAme字符的两个不同值转换为相同的QName。