Eclipse中XSLT输出多余msxsl命名空间问题求助
我之前从Visual Studio的MSXML处理器切换到Eclipse的Xalan/Saxon处理器时,也碰到过一模一样的命名空间处理差异问题。核心原因是不同XSLT处理器对命名空间继承和前缀输出的逻辑不一样:VS的MSXML会自动复用父节点的命名空间声明,而Eclipse里的处理器会严格按照你XSLT中的命名空间绑定来输出前缀,哪怕完全没必要。
针对你的情况,有几个简单的修复方案:
方案1:让MessageType继承父节点的命名空间
原XSLT中你用xsl:element显式指定了命名空间,但父节点CustInvoiceJour已经处于http://schemas.microsoft.com/dynamics/2008/01/documents/SalesInvoice命名空间下,完全可以去掉namespace属性,让元素自动继承上下文的命名空间:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="http://schemas.microsoft.com/dynamics/2008/01/documents/SalesInvoice"> <xsl:output method="xml" indent="yes" /> <xsl:strip-space elements="*" /> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="msxsl:SalesType"> <xsl:choose> <xsl:when test="(../msxsl:SalesType) = 'ReturnItem'"> <xsl:element name="MessageType">384</xsl:element> </xsl:when> <xsl:otherwise> <xsl:element name="MessageType">380</xsl:element> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
这样修改后,Eclipse的处理器会自动让MessageType继承父节点的命名空间,不会额外添加msxsl前缀和声明。
方案2:设置默认命名空间并排除多余前缀
如果你希望更明确地控制命名空间,可以把目标命名空间设为XSLT的默认命名空间,同时用exclude-result-prefixes告诉处理器不要输出msxsl前缀:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="http://schemas.microsoft.com/dynamics/2008/01/documents/SalesInvoice" xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/SalesInvoice" exclude-result-prefixes="msxsl"> <xsl:output method="xml" indent="yes" /> <xsl:strip-space elements="*" /> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="msxsl:SalesType"> <xsl:choose> <xsl:when test="(../msxsl:SalesType) = 'ReturnItem'"> <MessageType>384</MessageType> </xsl:when> <xsl:otherwise> <MessageType>380</MessageType> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
这里直接输出<MessageType>即可,因为默认命名空间已经和目标命名空间一致,exclude-result-prefixes="msxsl"会阻止处理器在输出中添加msxsl的命名空间声明。
为什么VS里没问题?
Visual Studio使用的MSXML处理器在命名空间处理上更灵活,当它检测到子节点的命名空间和父节点完全一致时,会自动省略前缀和重复的命名空间声明,而Eclipse常用的Xalan或Saxon处理器则会严格遵循XSLT中的命名空间绑定规则,所以才会出现这种差异。
内容的提问来源于stack exchange,提问作者Mike Dole

