XSLT 1.0处理前缀未知的固定命名空间XML的解决方案咨询
问题描述
尝试构建XSLT 1.0样式表处理命名空间固定但前缀未知且可变的XML文档时,出现“未声明前缀”错误,求最优解决策略;若已知命名空间URI,能否将所有前缀重新分配为XSLT中预定义的对应前缀?具体实现方式是怎样的?
示例源XML:
<unknownPrefix:root xmlns:unknownPrefix="knownURI" xmlns:unknownPrefix2="knownURI2" xmlns:unknownPrefix3="knownURI3" > <unknownPrefix2:node unknownPrefix3:someattribute="example">text</unknownprefix2:node> </unknownPrefix:root>
解决策略与实现
一、最优解决核心:忽略前缀,匹配命名空间URI
XML的命名空间核心是URI而非前缀,前缀只是URI的别名,完全可以在XSLT中绕过前缀,直接通过namespace-uri()和local-name()来匹配节点,从根源避免“未声明前缀”错误。
二、已知URI时,重分配前缀为预定义值的实现
完全可以将源XML中所有未知前缀的节点,替换为XSLT预定义的固定前缀,具体步骤如下:
1. 在XSLT中预定义前缀与已知URI的映射
先在样式表头部声明你想要的固定前缀,绑定到已知的命名空间URI:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="knownURI" <!-- 对应源XML的knownURI --> xmlns:ns2="knownURI2" <!-- 对应源XML的knownURI2 --> xmlns:ns3="knownURI3" <!-- 对应源XML的knownURI3 --> exclude-result-prefixes="ns1 ns2 ns3"> <!-- 避免这些前缀出现在输出的根元素声明中(可选) -->
2. 处理元素:替换前缀
通过判断元素的命名空间URI,创建使用预定义前缀的新元素:
<!-- 匹配所有元素,按命名空间替换前缀 --> <xsl:template match="*"> <xsl:choose> <!-- 匹配knownURI下的元素,用ns1前缀 --> <xsl:when test="namespace-uri()='knownURI'"> <xsl:element name="ns1:{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:when> <!-- 匹配knownURI2下的元素,用ns2前缀 --> <xsl:when test="namespace-uri()='knownURI2'"> <xsl:element name="ns2:{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:when> <!-- 匹配knownURI3下的元素,用ns3前缀 --> <xsl:when test="namespace-uri()='knownURI3'"> <xsl:element name="ns3:{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:when> <!-- 处理其他命名空间或无命名空间的元素(可选) --> <xsl:otherwise> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:template>
3. 处理属性:替换前缀
同样的逻辑处理带命名空间的属性:
<!-- 匹配所有属性,按命名空间替换前缀 --> <xsl:template match="@*"> <xsl:choose> <xsl:when test="namespace-uri()='knownURI'"> <xsl:attribute name="ns1:{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:when> <xsl:when test="namespace-uri()='knownURI2'"> <xsl:attribute name="ns2:{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:when> <xsl:when test="namespace-uri()='knownURI3'"> <xsl:attribute name="ns3:{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:copy/> </xsl:otherwise> </xsl:choose> </xsl:template>
4. 处理文本节点等其他节点
保留文本、注释、处理指令等节点,直接复制:
<xsl:template match="text()|comment()|processing-instruction()"> <xsl:copy/> </xsl:template>
三、完整XSLT示例
将上述片段组合,完整样式表如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="knownURI" xmlns:ns2="knownURI2" xmlns:ns3="knownURI3" exclude-result-prefixes="ns1 ns2 ns3"> <xsl:template match="*"> <xsl:choose> <xsl:when test="namespace-uri()='knownURI'"> <xsl:element name="ns1:{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:when> <xsl:when test="namespace-uri()='knownURI2'"> <xsl:element name="ns2:{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:when> <xsl:when test="namespace-uri()='knownURI3'"> <xsl:element name="ns3:{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="@*"> <xsl:choose> <xsl:when test="namespace-uri()='knownURI'"> <xsl:attribute name="ns1:{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:when> <xsl:when test="namespace-uri()='knownURI2'"> <xsl:attribute name="ns2:{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:when> <xsl:when test="namespace-uri()='knownURI3'"> <xsl:attribute name="ns3:{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:copy/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="text()|comment()|processing-instruction()"> <xsl:copy/> </xsl:template> </xsl:stylesheet>
四、输出结果
用上述样式表处理示例XML,将得到:
<ns1:root xmlns:ns1="knownURI" xmlns:ns2="knownURI2" xmlns:ns3="knownURI3" > <ns2:node ns3:someattribute="example">text</ns2:node> </ns1:root>
内容的提问来源于stack exchange,提问作者Koolan
相关产品推荐
相关产品推荐

