在xslt中更改名称空间uri

时间:2017-10-11 08:37:17

标签: xml xslt xml-namespaces

我正在尝试转换Enterprise Architect生成的xmi文件,以便eclipse工具接受它。

我需要改变的一件事是前缀 uml:的命名空间uri,从“http://www.omg.org/spec/UML/20090901”到“http://www.eclipse.org/uml2/2.0.0/UML

输入:

<?xml version="1.0" encoding="windows-1252"?>
<xmi:XMI xmi:version="2.1" 
xmlns:uml="http://www.omg.org/spec/UML/20090901" 
xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" >
    <xmi:Documentation exporter="Enterprise Architect" exporterVersion="6.5"/>
    <uml:Model xmi:type="uml:Model" name="EA_Model">
    <!-- content of the model -->
    </uml:Model>
</xmi:XMI>

预期产出:

<?xml version="1.0" encoding="windows-1252"?>
<xmi:XMI xmi:version="2.1" xmlns:uml="http://www.eclipse.org/uml2/2.0.0/UML"
xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" >
    <xmi:Documentation exporter="Enterprise Architect" exporterVersion="6.5"/>
    <uml:Model xmi:type="uml:Model" name="EA_Model">
    <!-- content of the model -->
    </uml:Model>
</xmi:XMI>

我尝试了什么:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xmi="http://schema.omg.org/spec/XMI/2.1"
xmlns:uml="http://www.omg.org/spec/UML/20090901"
 exclude-result-prefixes="#all">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- update uml:namespace to "http://www.eclipse.org/uml2/2.0.0/UML" -->
        <xsl:template match="uml:*">
        <xsl:element name="{local-name()}" namespace="http://www.eclipse.org/uml2/2.0.0/UML">
            <xsl:apply-templates select="@*, node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

但是从节点中删除了uml:前缀并为其添加了一个默认命名空间。

要绝对清楚,我需要的只是字符串

xmlns:uml="http://www.omg.org/spec/UML/20090901"

替换为

xmlns:uml="http://www.eclipse.org/uml2/2.0.0/UML"

2 个答案:

答案 0 :(得分:2)

name="{local-name()}"替换为name="uml:{local-name()}"

如果您没有指定前缀,系统就不会使用前缀。

答案 1 :(得分:2)

这会产生所需的结果:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="#all" version="3.0"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:xmi="http://schema.omg.org/spec/XMI/2.1"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="windows-1252" indent="yes" method="xml" version="1.0"/>

    <xsl:template match="uml:*" xmlns:uml="http://www.omg.org/spec/UML/20090901">
        <xsl:element name="{name()}" namespace="http://www.eclipse.org/uml2/2.0.0/UML">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@* | node()">
        <xsl:copy copy-namespaces="no">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="xmi:XMI">
        <xmi:XMI xmi:version="2.1"
            xmlns:uml="http://www.eclipse.org/uml2/2.0.0/UML"
            xmlns:xmi="http://schema.omg.org/spec/XMI/2.1">
            <xsl:apply-templates select="@* | node()"/>
        </xmi:XMI>
    </xsl:template>

</xsl:stylesheet>

我确信有一个更简单的解决方案。但这可能是一个开始。

扩展答案(请参阅评论中的问题):将第三个模板替换为复制除xmlns:uml以外的所有名称空间声明。

<xsl:template match="xmi:XMI">
    <xmi:XMI xmi:version="2.1" xmlns:uml="http://www.eclipse.org/uml2/2.0.0/UML">
        <xsl:copy-of select="namespace-node()[not(. = 'http://www.omg.org/spec/UML/20090901')]"/>
        <xsl:apply-templates select="@* | node()"/>
    </xmi:XMI>
</xsl:template>