XSLT更改名称空间前缀

时间:2015-05-25 04:42:36

标签: xml xslt xpath

我正在尝试将属性转换为元素,同时,我想更改我的XML代码的名称空间前缀。 XML代码:

    <lm:GetInvoiceList xmlns:lm="http://www.w3.org">
    <lm:Response>
    <lm:Bill>
    <lm:BillStatusCode typecode="1">type description</lm:BillStatusCode>
    <lm:EBillProcessStatusCode typecode="2">type description</lm:EBillProcessStatusCode>
    <lm:BillCycleCode typecode="1">type description</lm:BillCycleCode>
    <lm:BillActivityCode typecode="3">type description</lm:BillActivityCode>
    <lm:ToDate>...</lm:ToDate>
    </lm:Bill>
    </lm:Response>
    </lm:GetInvoiceList>

我有这个XSLT代码:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()">
    <xsl:copy>
    <xsl:apply-templates/>
    </xsl:copy>
    </xsl:template>

    <xsl:template match="*[@*]">
    <xsl:copy>
    <xsl:element name="ns:{name()}">
    <xsl:apply-templates select="node()"/>
    </xsl:element>
    <xsl:apply-templates select="@*"/>
    </xsl:copy>
    </xsl:template>
    <xsl:template match="*|*[@*]">
    <xsl:element name="ns:{local-name()}" namespace="http://my.ns.uri">
    <xsl:copy-of select="namespace::*"/>
    <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
    <xsl:element name="ns:{name()}" namespace="http://my.ns.uri">
    <xsl:copy-of select="namespace::*"/>
    <xsl:value-of select="."/>
    </xsl:element>
    </xsl:template>
    </xsl:stylesheet>

但我没有得到所需的输出。

预期产出:

    <ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
    <ns:Response>
    <ns:Bill>
    <ns:BillStatusCode>
    <ns:BillStatusCode>type description</ns:BillStatusCode>
    <ns:typecode>1</ns:typecode>
    </ns:BillStatusCode>
    <ns:EBillProcessStatusCode>
    <ns:EBillProcessStatusCode>type description</ns:EBillProcessStatusCode>
    <ns:typecode>2</ns:typecode>
    </ns:EBillProcessStatusCode>
    <ns:BillCycleCode>
    <ns:BillCycleCode>type description</ns:BillCycleCode>
    <ns:typecode>1</ns:typecode>
    </ns:BillCycleCode>
    <ns:BillActivityCode>
    <ns:BillActivityCode>type description</ns:BillActivityCode>
    <ns:typecode>3</ns:typecode>
    </ns:BillActivityCode>
    <ns:ToDate>...</ns:ToDate>
    </ns:Bill>
    </ns:Response>
    </ns:GetInvoiceList>

实际输出:

   <ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
   <ns:Response>
   <ns:Bill>
   <ns:BillStatusCode>
   <ns:typecode>1</ns:typecode>type description</ns:BillStatusCode>
   <ns:EBillProcessStatusCode>
   <ns:typecode>2</ns:typecode>type description</ns:EBillProcessStatusCode>
   <ns:BillCycleCode>
   <ns:typecode>1</ns:typecode>type description</ns:BillCycleCode>
   <ns:BillActivityCode>
   <ns:typecode>3</ns:typecode>type description</ns:BillActivityCode>
   <ns:ToDate>...</ns:ToDate>
   </ns:Bill>
   </ns:Response>
   </ns:GetInvoiceList>

会对此提出任何帮助!

2 个答案:

答案 0 :(得分:2)

鉴于您在评论中的澄清,我建议:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://my.ns.uri">
<xsl:output method="xml" version="1.0" omit-xml-declaration="yes" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

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

<xsl:template match="@*">
    <xsl:element name="ns:{local-name()}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

有什么区别?

当应用于以下示例输入时:

<强> XML

<lm:GetInvoiceList xmlns:lm="http://www.w3.org">
   <lm:Response>
      <lm:Bill>
         <lm:BillPropertyA subPropertyA="first subproperty">first property</lm:BillPropertyA>
         <lm:BillPropertyB subPropertyB="second subproperty"/>
         <lm:BillPropertyC>second property</lm:BillPropertyC>
      </lm:Bill>
   </lm:Response>
</lm:GetInvoiceList>

结果将是:

<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
   <ns:Response>
      <ns:Bill>
         <ns:BillPropertyA>
            <ns:BillPropertyA>first property</ns:BillPropertyA>
            <ns:subPropertyA>first subproperty</ns:subPropertyA>
         </ns:BillPropertyA>
         <ns:BillPropertyB>
            <ns:BillPropertyB/>
            <ns:subPropertyB>second subproperty</ns:subPropertyB>
         </ns:BillPropertyB>
         <ns:BillPropertyC>second property</ns:BillPropertyC>
      </ns:Bill>
   </ns:Response>
</ns:GetInvoiceList>

而不是:

<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
   <ns:Response>
      <ns:Bill>
         <ns:BillPropertyA>
            <ns:subPropertyA>first subproperty</ns:subPropertyA>
            <ns:BillPropertyA>first property</ns:BillPropertyA>
         </ns:BillPropertyA>
         <ns:BillPropertyB>
            <ns:subPropertyB>second subproperty</ns:subPropertyB>
         </ns:BillPropertyB>
         <ns:BillPropertyC>
            <ns:BillPropertyA>second property</ns:BillPropertyA>
         </ns:BillPropertyC>
      </ns:Bill>
   </ns:Response>
</ns:GetInvoiceList>

将“第二个属性”文本节点错误地放在ns:BillPropertyA的另一个实例下,并使其成为ns:BillPropertyC的子项。

备注

  1. 如果要更改节点的命名空间,则无法使用 xsl:copy,因为这也会复制现有的命名空间;

  2. 您可以(并且应该)声明命名空间一次,然后使用 必要时已经存在绑定。

答案 1 :(得分:1)

试试这个XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="text()">
    <xsl:element name="ns:{local-name(../../*)}" namespace="http://my.ns.uri">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:element name="ns:{local-name()}" namespace="http://my.ns.uri">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

输出:

<ns:GetInvoiceList xmlns:ns="http://my.ns.uri">
  <ns:Response>
    <ns:Bill>
      <ns:BillStatusCode>
        <ns:typecode>1</ns:typecode>
        <ns:BillStatusCode>type description</ns:BillStatusCode>
      </ns:BillStatusCode>
      <ns:EBillProcessStatusCode>
        <ns:typecode>2</ns:typecode>
        <ns:BillStatusCode>type description</ns:BillStatusCode>
      </ns:EBillProcessStatusCode>
      <ns:BillCycleCode>
        <ns:typecode>1</ns:typecode>
        <ns:BillStatusCode>type description</ns:BillStatusCode>
      </ns:BillCycleCode>
      <ns:BillActivityCode>
        <ns:typecode>3</ns:typecode>
        <ns:BillStatusCode>type description</ns:BillStatusCode>
      </ns:BillActivityCode>
      <ns:ToDate>
        <ns:BillStatusCode>...</ns:BillStatusCode>
      </ns:ToDate>
    </ns:Bill>
  </ns:Response>
</ns:GetInvoiceList>