在基于XSL的转换后删除空xmlns元素

在基于XSL的转换后删除空xmlns元素,xml,xslt,transformation,xml-namespaces,Xml,Xslt,Transformation,Xml Namespaces,最近,我一直在使用一个数据转换工具,它使用XSL修改输入数据的格式。我最近遇到了一个新的问题,这是由前一个问题的解决方案引起的 正确的xmlns存储在父元素中,但第一个子元素(唯一的第一级子节点)包含一个属性xmlns=“”。我发现了一些类似的问题,但问题/实现方法不同,足以阻止我直接应用更改。有人知道如何阻止该属性应用于子数据吗?我曾考虑过沿着我以前走过的路走下去(通过序列化XML,然后执行字符串操作来修复它),但所需的序列化函数只存在于xpath 3中,我使用的转换服务器只支持xpath 2

最近,我一直在使用一个数据转换工具,它使用XSL修改输入数据的格式。我最近遇到了一个新的问题,这是由前一个问题的解决方案引起的

正确的xmlns存储在父元素中,但第一个子元素(唯一的第一级子节点)包含一个属性
xmlns=“”
。我发现了一些类似的问题,但问题/实现方法不同,足以阻止我直接应用更改。有人知道如何阻止该属性应用于子数据吗?我曾考虑过沿着我以前走过的路走下去(通过序列化XML,然后执行字符串操作来修复它),但所需的序列化函数只存在于xpath 3中,我使用的转换服务器只支持xpath 2,遗憾的是,我没有发言权:(

我正在使用Map Force构建XSL转换,因此不能简单地编辑XSL(因为它将被Map Force覆盖),但我相信我可以对Map Force应用XSL更改

XSLT的一个片段

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:core="http://www.altova.com/MapForce/UDF/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="core xs fn">
    <xsl:template name="core:firstCharacter">
        ...
    </xsl:template>
    <xsl:template name="core:tokenize-by-length-internal">
        ...
    </xsl:template>
    <xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="var1_SwiftMessages" as="node()?" select="SwiftMessages"/>
        <xformResult xmlns="urn:...">
            <xsl:attribute name="xsi:schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance" select="'urn:... OutputInterface/xformResult.xsd'"/>
            <xformResultRecord>
                <xformResultData>
                    <Document>
                        <!-- REMAINDER OF FAIRLY STANDARD CODE -->
                    </Document>
                </xformResultData>
            </xformResultRecord>
        </xformResult>
    </xsl:template>

如您所见,
Document
Cstmr
)的第一级子级具有
xmlns=“”
通过transformer输出添加到元素中。当我使用Map Force对此进行测试时,它不包括在内,但它包含在xform工具的输出中。xform工具基于SAXON,对它的调用是相当标准的XML函数。

在转换的其他地方(或输入数据)一定有问题.这不是一个系列化的问题

下面的两个示例具有不同的含义。在第一个示例中,
body
在根元素上设置了默认的xhtml名称空间

<html xmlns="http://www.w3.org/1999/xhtml">
<body>
</body>
</html>
编辑:

如果可以选择执行其他转换,则以下XSLT将把父级名称空间(实际上是最接近的合适祖先的名称空间)应用于名称空间为空的元素:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template priority="2" match="*">
        <xsl:choose>
            <xsl:when test="namespace-uri()=''">
                <xsl:element name="{local-name()}" namespace="{namespace-uri(ancestor::*[namespace-uri()!=''][1])}">
                    <xsl:apply-templates select="@* | node()"/>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
                    <xsl:apply-templates select="@* | node()"/>
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template priority="1" match="@* | node()">
        <xsl:copy-of select="."/>
    </xsl:template>

</xsl:stylesheet>

Edit2:

这是一个允许模式,它将验证任何内容,您只需要根元素的名称和命名空间(对于模式的targetNamespace属性)

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.w3.org/1999/xhtml"
    elementFormDefault="qualified">

  <xs:element name="html">
    <xs:complexType>
      <xs:sequence>
        <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

命名空间声明不是属性,即使它们看起来相同。如果您有
xmlns=“”
出现在输出中的某个元素上,则意味着您将一个没有名称空间的元素添加到树中的某个点上,该点上存在已生效的默认名称空间。为了输出这样的结构,序列化程序必须使用
xmlns=“”
取消该默认值

要解决这个问题,您需要在正确的名称空间中创建元素

<example xmlns="http://example.com">
  <child1/>
</example>
会产生和你看到的一样的结果

<example xmlns="http://example.com">
  <child2 xmlns=""/>
</example>
然后它将产生正确的结果

<example xmlns="http://example.com">
  <child2 />
</example>

然后,这将把所有未固定的文本结果元素放入
urn:…
名称空间,包括
Cstmr

生成空名称空间的XSLT是什么样子的?您没有向我们展示生成Cstmr元素的代码,因此很难建议您如何更改它。无论代码是什么,它的名称都是空的在没有命名空间的情况下生成Cstmr元素,而它应该在urn:…命名空间中生成元素。这几乎就是我遇到的问题(但不是html,一种适当的xml表单)。
xmlns=“”
在您的
正文中
标记就是我在我的标签上看到的。但是如何阻止Map Force强行插入
xmlns=“”
?从我在internet上发现的情况来看,填充数据的模板似乎不在名称空间中,因此它被插入到默认名称空间中(即
),因此我需要找到一种方法来阻止Map Force在应该继承名称空间时认为名称空间是不同的it@cgoddard共享生成的XSLT可能会有所帮助。(如果不是机密的话。)超级机密(显然,银行似乎认为社区内共享的信息无法传播到更广泛的世界,以至于要获得规范,你需要签署一份200页的NDA…)。无论如何,xslt是巨大的,完整的映射是57k,超过2000行。这看起来很漂亮。我可以在这个过程中再做一步(目前有4个,这是最后一个转换),因此我可以直接将其作为XSL转换(不使用mapforce)放在末尾,并使用它删除任何空名称空间。谢谢,我会让您知道它是如何工作的,Dammit已经给了您一个+1,如果SE允许的不仅仅是+1和-1来判断的话(我知道答案是马克,但那只适用于它起作用的时候)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <!-- replace children of the document element with child2 -->
  <xsl:template match="/*/*">
    <child2 /><!-- child2 is in no namespace -->
  </xsl:template>
</xsl:stylesheet>
<example xmlns="http://example.com">
  <child2 xmlns=""/>
</example>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns="http://example.com">
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <!-- replace children of the document element with child2 -->
  <xsl:template match="/*/*">
    <child2 /><!-- child2 is now in the http://example.com namespace -->
  </xsl:template>
</xsl:stylesheet>
<example xmlns="http://example.com">
  <child2 />
</example>
  <xsl:template match="/*/*" xmlns="http://example.com">
    <child2/>
  </xsl:template>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:core="http://www.altova.com/MapForce/UDF/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="core xs fn">
    <xsl:template name="core:firstCharacter">
        ...
    </xsl:template>
    <xsl:template name="core:tokenize-by-length-internal">
        ...
    </xsl:template>
    <xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="var1_SwiftMessages" as="node()?" select="SwiftMessages"/>
        <xformResult xmlns="urn:...">
            <xsl:attribute name="xsi:schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance" select="'urn:... OutputInterface/xformResult.xsd'"/>
            <xformResultRecord>
                <xformResultData>
                    <Document>
                        <!-- example of code that might be in here -->
                        <xsl:apply-templates select="$var1_SwiftMessages/Customer" />
                    </Document>
                </xformResultData>
            </xformResultRecord>
        </xformResult>
    </xsl:template>

    <xsl:template match="Customer">
        <Cstmr>
            <!-- contents of Cstmr element -->
        </Cstmr>
    </xsl:template>
<xsl:stylesheet version="2.0" xmlns="urn:..." xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:core="http://www.altova.com/MapForce/UDF/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="core xs fn">
    <xsl:template name="core:firstCharacter">
        ...
    </xsl:template>
    <xsl:template name="core:tokenize-by-length-internal">
        ...
    </xsl:template>
    <xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="var1_SwiftMessages" as="node()?" select="SwiftMessages"/>
        <xformResult>
            <xsl:attribute name="xsi:schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance" select="'urn:... OutputInterface/xformResult.xsd'"/>
            <xformResultRecord>
                <xformResultData>
                    <Document>
                        <!-- example of code that might be in here -->
                        <xsl:apply-templates select="$var1_SwiftMessages/Customer" />
                    </Document>
                </xformResultData>
            </xformResultRecord>
        </xformResult>
    </xsl:template>

    <xsl:template match="Customer">
        <Cstmr>
            <!-- contents of Cstmr element -->
        </Cstmr>
    </xsl:template>