如何在不删除xmlns标记的情况下删除xml中的名称空间前缀?

时间:2014-03-10 19:05:17

标签: xml xslt namespaces

我正在尝试删除名称空间前缀。我尝试了几个XSLT但它们似乎没有用(在示例之后会显示原因)。

当前xml输出示例:

<s:Body     xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<ns:GetPriceSet     xmlns:ns="http://abc.org/01/02">
<ns:og>
    <TestElement1   xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
    <TestElement2   xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</ns:og>
</ns:GetPriceSet>
</s:Body>

我想要的是什么:

<s:Body     xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<GetPriceSet    xmlns="http://abc.org/01/02">
<og>
    <TestElement1   xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
    <TestElement2   xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</og>
</GetPriceSet>
</s:Body>

我尝试使用这里的两个XSLT:How to remove namespace prefix leaving namespace value (XSLT)?

问题是ns:被替换为ns0和ns1,而不是被XSLT完全删除。所以我假设需要进一步修改XSLT。

4 个答案:

答案 0 :(得分:0)

根据您分享的示例,它似乎应该有用吗?

<xsl:template match="ns:*">
        <xsl:element name="{local-name()}" >
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

答案 1 :(得分:0)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   xmlns:ns="http://abc.org/01/02">
    <xsl:output method="xml" version="1.0" indent="yes" encoding="UTF-8" standalone="yes"/>



<xsl:template match="ns:*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@* | *"/>
    </xsl:element>
 </xsl:template>

<xsl:template match="* | @*">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

在XML术语中,当前输出和所需输出之间的唯一(语义)差异是,在当前输出中,您有TestElement1TestElement2不在命名空间中,并且在您想要的输出中已被移动到与其父og元素相同的命名空间中。所以你可以做一些像

这样的事情
<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>

  <xsl:template match="ns:og/*" xmlns:ns="http://abc.org/01/02">
    <xsl:element name="ns:{local-name()}">
      <xsl:apply-templates select="node() | @*"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

应该产生

的输出
<s:Body     xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<ns:GetPriceSet     xmlns:ns="http://abc.org/01/02">
<ns:og>
    <ns:TestElement1   xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
    <ns:TestElement2   xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</ns:og>
</ns:GetPriceSet>
</s:Body>

就感知命名空间的XML解析器而言,这与您的“通缉”输出相同。

如果在实际示例中您的TestElement有孩子,那么您可能需要将ns:og//*而非ns:og/*与第二个模板匹配。

如果正在使用XML的服务在前缀上窒息(在这种情况下,它不应声称它可以处理XML,但那是另一个参数......)那么就可以移动{{ 1}}如果你更换第二个模板如下,进入目标名称空间而不用任何前缀:

s:Body

答案 3 :(得分:0)

这会产生完全你想要的东西! (如果不是,请告诉我!)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:foobar="http://abc.org/01/02">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

<xsl:template match="foobar:* | TestElement1 | TestElement2">
    <xsl:element name="{local-name()}" namespace="http://abc.org/01/02">
        <xsl:apply-templates select="node() | @*"  />
    </xsl:element>
 </xsl:template>

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

</xsl:stylesheet>