XSLT 1.0:xsl:如果测试xpath不适用于没有命名空间的标签?

时间:2014-03-12 11:29:54

标签: xml xslt xpath xslt-1.0 openxml

考虑以下XML:

<mergeddocx>

    <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">

        <w:hyperlink r:id="rId9">
            <w:r>
                <w:t>Hello World!!</w:t>
            </w:r>
        </w:hyperlink>

    </w:document>

    <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId9" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="http://x1y1z1.com/" TargetMode="External" />
    </Relationships>

</mergeddocx>

当我尝试使用以下XSL脚本解析它时:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
exclude-result-prefixes="w r">

<xsl:template match="w:hyperlink">
    <a>
        <xsl:variable name="rId">
            <xsl:value-of select="@r:id"/>
        </xsl:variable>
        <xsl:if test="/mergeddocx/Relationships">
            <xsl:attribute name="href">
                <xsl:value-of select="$rId"/>
            </xsl:attribute>
        </xsl:if>
        <xsl:attribute name="target">
            <xsl:text>_blank</xsl:text>
        </xsl:attribute>
    </a>
</xsl:template>

而不是获得预期的输出:

<a href="rId9" target="_blank">
</a>

我得到的是:

<a target="_blank"/>

xsl:if中的xpath不接受Relationships标记内有mergeddocx个标记。但是,当我在测试xpath中仅使用/mergeddocx时,它可以正常工作。

我在这里做错了什么?如何在我的xpath中包含非命名空间的标记?

Thanx提前!!

2 个答案:

答案 0 :(得分:2)

元素位于命名空间中,您错误地命名空间的命名空间前缀。

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">

xmlns属性将默认命名空间设置为其值。此元素和没有名称空间前缀的任何其他元素将位于此命名空间中。

所以节点的实际内部地址是:

{http://schemas.openxmlformats.org/package/2006/relationships}:Relationships 

这就是为什么在xslt中定义自己的名称空间前缀的原因。向您添加该命名空间的注册Xslt:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:rel="http://schemas.openxmlformats.org/package/2006/relationships"
exclude-result-prefixes="w r rel">

现在你可以使用它了:

mergeddocx/rel:Relationships

与元素节点不同,Xpath没有默认命名空间。要解决命名空间内的元素,您始终必须使用命名空间前缀。

答案 1 :(得分:2)

以这种方式尝试:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:rel="http://schemas.openxmlformats.org/package/2006/relationships"
exclude-result-prefixes="w r rel">

<xsl:template match="w:hyperlink">
    <a>
        <xsl:variable name="rId">
            <xsl:value-of select="@r:id"/>
        </xsl:variable>
        <xsl:if test="/mergeddocx/rel:Relationships">
            <xsl:attribute name="href">
                <xsl:value-of select="$rId"/>
            </xsl:attribute>
        </xsl:if>
        <xsl:attribute name="target">
            <xsl:text>_blank</xsl:text>
        </xsl:attribute>
    </a>
</xsl:template>

</xsl:stylesheet>

注意xmlns:r和xmlns:rel namespace之间的区别。它们不一样。