16

好的,我已经看到了这个问题的许多变体,但没有一个能准确回答我想要解决的问题,也许我太密集了,看不到如何将其他答案之一应用于我正在尝试做的事情。

我有一些类似于以下内容的 XML:

<?xml version="1.0" encoding="utf-8"?>
<message>
  <cmd id="api_info">
    <api-version>1.0</api-version>
    <api-build>1.0.0.0</api-build>
  </cmd>
</message>

现在我有一个 XSLT 转换,我正在应用到这个 XML。XSLT 类似于以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                version="2.0">

    <xsl:output method="xml" version="1.0" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates select="message"/>
    </xsl:template>

    <xsl:template match="message">
        <xsl:element name="message" xmlns="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/message/cmd/@id">
        <xsl:variable name="_commandType" select="/message/cmd/@id"/>
        <xsl:element name="messageHeader">
            <xsl:element name="cmdType">
                <xsl:value-of select="$_commandType"/>
            </xsl:element>
        </xsl:element>

        <xsl:element name="messageBody">
            <xsl:choose>
                <xsl:when test="$_commandType = 'api_info'">
                    <xsl:element name="apiInfoBody">
                        <xsl:element name="apiVersion">
                            <xsl:value-of select="/message/cmd/api-version"/>
                        </xsl:element>
                        <xsl:element name="apiBuild">
                            <xsl:value-of select="/message/cmd/api-build"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
                <xsl:when test="$_commandType = 'communicationError'">
                    <xsl:element name="communicationErrorBody">
                        <xsl:element name="errorCode">
                            <xsl:value-of select="error-code"/>
                        </xsl:element>
                        <xsl:element name="badCmd">
                            <xsl:value-of select="bad-cmd"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

我得到的输出基本上是我想要的,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<message xmlns="http://www.companyname.com/schemas/product/Version001">
    <messageHeader xmlns="">
        <cmdType>api_info</cmdType>
    </messageHeader>
    <messageBody xmlns="">
        <apiInfoBody>
            <apiVersion>1.0</apiVersion>
            <apiBuild>1.0.0.0</apiBuild>
        </apiInfoBody>
    </messageBody>
</message>

但我不想要的是 <messageHeader> 和 <messageBody> 元素中的xmlns = " "属性

现在我发现,如果我在 XSLT 中为这些元素显式指定名称空间,那么不需要的属性会被下推到这些属性的子级。

我可以浏览我的整个 XSLT 并将xmlns="" http://www.companyname.com/schemas/product/Version001 "属性显式添加到我的每个xsl:element定义中,但我知道必须有一个更优雅的方式。我们程序员太懒了,没有这种废话的捷径。如果我的 XSLT 不包含像缩短示例这样简单的东西,我很想这样做。但我知道那里必须是更好的方法。

有谁知道我在这里想念什么?

谢谢,

报警器

4

3 回答 3

11

在 xsl:stylesheet 标记上使用 exclude-result-prefixes 前缀“#default”

w3c 中对此的参考是HERE

编辑:好的,我应该更仔细地研究你的 XSL。将消息标记上的 xmlns 向上移动到样式表标记。这会将所有结果元素放在同一个命名空间中,并在消息标签上产生一个命名空间属性。我在 Oxygen/XML 中运行它并得到了你想要的输出。

于 2009-12-04T03:08:01.770 回答
0

好的,我想通了。

我想要的 XSLT 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                exclude-result-prefixes="xsl fo xs fn">

    <xsl:output method="xml" version="1.0" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates select="message"/>
    </xsl:template>

    <xsl:template match="message">
        <message namespace="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </message>
    </xsl:template>

    <xsl:template match="/message/cmd/@id">
        <xsl:variable name="_commandType" select="/message/cmd/@id"/>

        <xsl:element name="messageHeader">
            <xsl:element name="cmdType">
                <xsl:value-of select="$_commandType"/>
            </xsl:element>
        </xsl:element>

        <xsl:element name="messageBody">
            <xsl:choose>
                <xsl:when test="$_commandType = 'api_info'">
                    <xsl:element name="apiInfoBody">
                        <xsl:element name="apiVersion">
                            <xsl:value-of select="/message/cmd/api-version"/>
                        </xsl:element>
                        <xsl:element name="apiBuild">
                            <xsl:value-of select="/message/cmd/api-build"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
                <xsl:when test="$_commandType = 'communicationError'">
                    <xsl:element name="communicationErrorBody">
                        <xsl:element name="errorCode">
                            <xsl:value-of select="error-code"/>
                        </xsl:element>
                        <xsl:element name="badCmd">
                            <xsl:value-of select="bad-cmd"/>
                        </xsl:element>
                    </xsl:element>
                </xsl:when>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

修复它的更改是将exclude-result-prefixes属性添加到<xsl:stylesheet>元素并更改以下部分:

    <xsl:template match="message">
        <xsl:element name="message" xmlns="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </xsl:element>
    </xsl:template>

改为以下:

    <xsl:template match="message">
        <message namespace="http://www.companyname.com/schemas/product/Version001">
            <xsl:apply-templates select="/message/cmd/@id"/>
        </message>
    </xsl:template>

现在我又开心了。

可能有更好的方法可以做到这一点,但这对我有用。任何未来的建议仍然欢迎。

于 2009-12-04T04:38:40.047 回答
0

Jim Garrison 的(更新的)答案就是您所需要的。但是您发布的更新样式表会在结果中输出一个“命名空间”属性,所以我不确定这对您有什么好处。

要理解的关键是默认命名空间是如何工作的。不要将 xmlns 视为可以输出到结果的属性。相反,将其视为样式表的词汇细节,其目的是为其下的所有内容(元素本身及其每个后代,直到被覆盖)设置默认命名空间。(反过来,它在结果 XML 中具有相同的功能,其结构与样式表本身非常不同。)

当提供的名称不使用时,样式表中的文字结果元素(例如,<message>)以及 <xsl:element> 指令(例如,<xsl:element name="message">)都采用默认命名空间一个前缀。如果您希望它们采用相同的名称空间,那么您需要在样式表的顶部放置一个默认名称空间,正如 Jim Garrison 建议的那样。

否则,您最终会得到一些不在该命名空间中的元素,这就是结果包含 xmlns="" 的原因(取消设置这些元素的命名空间)。

于 2009-12-07T21:46:24.240 回答