使用Apache Xalan对XML进行XSLT转换后,缺少名称空间前缀

时间:2011-05-24 17:32:40

标签: xslt namespaces transform xml-namespaces

我有以下XML:

<?xml version="1.0"?>
    <abc:Element1 xmlns:abc="http://..../resources/abc/v2/"
         ...>
         <abc:Element2>
            <abc:Element3s>
                 <abc:Element4 name="name1"
                               resourceRef="name2"/>
            </abc:Element3s>
         </abc:Element2>

         <abc:Resources>
            <abc:Resource xsi:type="abc:Something"
                          name="name2"/>
         </abc:Resources>
     </abc:Element1>   

...和这个XSLT样式表:

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:abc="http://.../resources/abc/v2/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:template match="/">
     <checker name="something">
       <xsl:for-each select="abc:Element1/abc:Element2/abc:Element3s/abc:Element4">
        <xsl:variable name="resource" select="@resourceRef"/>
        <xsl:variable name="xsiType"><xsl:value-of select="//abc:Resource[@name=$resource]/@xsi:type"/></xsl:variable>
        <xsl:choose>
            <xsl:when test="$xsiType='abc:Something'">
               ...
            </xsl:when>
            <xsl:otherwise>
               ...
            </xsl:otherwise>
         </xsl:choose>
       </xsl:for-each>
     </checker>
   </xsl:template>
</xsl:stylesheet>

我正在使用XALAN 2.7.1和org.apache.xalan.xsltc.trax.TransformerFactoryImpl(也尝试使用org.apache.xalan.processor.TransformerFactoryImpl - &gt;相同的结果)来转换XML。

我希望以下行在变量 xsiType 中存储 abc:Something

<xsl:variable name="xsiType"><xsl:value-of select="//abc:Resource[@name=$resource]/@xsi:type"/></xsl:variable>

但不幸的是只有 Something (没有名称空间作为前缀)存储在 xsiType 中。我验证了这一点,因为

<xsl:when test="$xsiType='abc:Something'">

不是真的。

我还使用 xsltproc 转换了XMl,结果XML看起来像预期的那样。因此,我希望输入XML / XSLT样式表是正确的。我假设Xalan及其配置有问题。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

您的样本数据格式不正确,因此很难说清楚。这可能是命名空间问题。这是输入和样式表的清理版本,用于提取所需的数据:

<?xml version="1.0"?>
<abc:Element1
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:abc="http://resources/abc/v2">
    <abc:Element2>
        <abc:Element3s>
            <abc:Element4 name="name1" resourceRef="name2"/>
        </abc:Element3s>
    </abc:Element2>
    <abc:Resources>
        <abc:Resource xsi:type="abc:Something" name="name2"/>
    </abc:Resources>
</abc:Element1>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:abc="http://resources/abc/v2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    exclude-result-prefixes="abc xsi"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="resource" select="'name2'"/>
        <xsl:variable name="type"
            select="//abc:Resource[@name=$resource]/@xsi:type"/>
        <checker name="{ $type }"/>
    </xsl:template>
</xsl:stylesheet>

这将产生:

<?xml version="1.0"?>
<checker name="abc:Something"/>

答案 1 :(得分:1)

在我看来,这是一个特定于Xalan的问题。然而,它可能是底层XML解析器的问题:Sun JDK中的默认解析器有一些奇怪的错误,包括一些破坏属性值的错误。始终使用Apache版本的Xalan和Xerces而不是JDK附带的版本。当然,如果您使用的是Xalan,那么切换到Saxon的成本几乎为零,这将为您提供XSLT 2.0的所有优势。