使用xslt从xml中删除父节点

时间:2015-05-25 19:18:27

标签: xml xslt

我需要将一个XML文件转换为另一个XML文件,删除一些父节点。

INPTUT Xml:

student

在xml输出文件中,我只需要节点&#34; <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:autorizacionComprobanteResponse xmlns:ns2="http://ec.gob.sri.ws.autorizacion"> <RespuestaAutorizacionComprobante> <claveAccesoConsultada>2</claveAccesoConsultada> <numeroComprobantes>1</numeroComprobantes> <autorizaciones> <autorizacion> <estado>AUTORIZADO</estado> <numeroAutorizacion>2</numeroAutorizacion> <fechaAutorizacion>2015-05-21T14:22:30.764-05:00</fechaAutorizacion> <ambiente>PRUEBAS</ambiente> <comprobante> <factura id="comprobante" version="1.0.0"> <infoTributaria> <ambiente>1</ambiente><tipoEmision>1</tipoEmision> </infoTributaria> </factura> </comprobante> <mensajes> <mensaje> <identificador>60</identificador> </mensaje> </mensajes> </autorizacion> </autorizaciones> </RespuestaAutorizacionComprobante> </ns2:autorizacionComprobanteResponse> </soap:Body> </soap:Envelope> &#34;没有&#34; <autorizacion>&#34;像这样的子节点:

所需的xml输出:

<mensajes>

我是xslt的新手,但我尝试了几个示例,此代码获得最接近的输出:

Xsl文件:

<autorizacion>
    <estado>AUTORIZADO</estado>
    <numeroAutorizacion>2</numeroAutorizacion>
    <fechaAutorizacion>2015-05-21T14:22:30.764-05:00</fechaAutorizacion>
    <ambiente>PRUEBAS</ambiente>
    <comprobante>
        <factura id="comprobante" version="1.0.0">
            <infoTributaria><ambiente>1</ambiente><tipoEmision>1</tipoEmision>
        </factura>
    </comprobante>
</autorizacion>

这是我用xsl获得的xml文件:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="autorizacion">
        <xsl:copy-of select="." />
    </xsl:template>
    <xsl:template match="mensajes"/>
</xsl:stylesheet>

我不知道为什么2 1 <autorizacion xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://ec.gob.sri.ws.autorizacion"> <estado>AUTORIZADO</estado> <numeroAutorizacion>2</numeroAutorizacion> <fechaAutorizacion>2015-05-21T14:22:30.764-05:00</fechaAutorizacion> <ambiente>PRUEBAS</ambiente> <comprobante> <factura id="comprobante" version="1.0.0"> <infoTributaria><ambiente>1</ambiente><tipoEmision>1</tipoEmision> </factura> </comprobante> <mensajes> <mensaje> <identificador>60</identificador> </mensaje> </mensajes> </autorizacion> xmlns:soap标记已添加到节点xmlns:ns2,并且<autorizacion>节点仍然存在。请帮我解决这个问题,我还需要删除空行,但如果可能的话还要保留缩进。

3 个答案:

答案 0 :(得分:1)

mensajes节点仍然存在,因为您复制了autorizacion节点。将模板应用于autorizacion的内容时,匹配mensajes的空模板将删除此元素 autorizacion的父节点的名称空间被添加到输出中。要删除命名空间,例如可以编写autorizacion以及没有命名空间的子节点,如下所示:

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

此模板匹配任何节点,使用当前匹配节点的名称创建元素,并将模板应用于所有属性和子节点,而不添加任何命名空间。
要删除empy行和空格,可以使用<xsl:strip-space elements="*"/>

以下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:apply-templates select="//autorizacion" />
  </xsl:template>
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
  </xsl:template>
  <xsl:template match="@*">
    <xsl:attribute name="{local-name(.)}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
  <xsl:template match="mensajes"/>
</xsl:stylesheet>

当应用于您的输入时,XML会生成输出

<autorizacion>
  <estado>AUTORIZADO</estado>
  <numeroAutorizacion>2</numeroAutorizacion>
  <fechaAutorizacion>2015-05-21T14:22:30.764-05:00</fechaAutorizacion>
  <ambiente>PRUEBAS</ambiente>
  <comprobante>
  <factura id="comprobante" version="1.0.0">
     <infoTributaria>
        <ambiente>1</ambiente>
        <tipoEmision>1</tipoEmision>
     </infoTributaria>
    </factura>
  </comprobante>
</autorizacion>

答案 1 :(得分:1)

要在复制时删除命名空间,只需要说copy-namespaces='no'即可。此外,您可能需要考虑使用strip-space删除转换生成的所有空格。最后,您只需要提及需要排除的节点。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:ns2="http://ec.gob.sri.ws.autorizacion"
   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

<xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>


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


<xsl:template match="@*|node()[not(self::mensajes) and (ancestor::autorizacion)]">
    <xsl:copy copy-namespaces='no'>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>


 <xsl:template match="mensajes|claveAccesoConsultada|numeroComprobantes"/>

 </xsl:stylesheet>

输出是:

<autorizacion>
   <estado>AUTORIZADO</estado>
   <numeroAutorizacion>2</numeroAutorizacion>
   <fechaAutorizacion>2015-05-21T14:22:30.764-05:00</fechaAutorizacion>
   <ambiente>PRUEBAS</ambiente>
   <comprobante>
      <factura id="comprobante" version="1.0.0">
         <infoTributaria>
            <ambiente>1</ambiente>
            <tipoEmision>1</tipoEmision>
         </infoTributaria>
      </factura>
   </comprobante>
</autorizacion>

答案 2 :(得分:0)

我认为身份变换略有不同:

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

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

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

  <xsl:template match="mensajes"/>
</xsl:stylesheet>

我不知道这与其他答案如何叠加,这看起来都是身份变换的。这是我得到的输出:

<autorizacion>
  <estado>AUTORIZADO</estado>
  <numeroAutorizacion>2</numeroAutorizacion>
  <fechaAutorizacion>2015-05-21T14:22:30.764-05:00</fechaAutorizacion>
  <ambiente>PRUEBAS</ambiente>
  <comprobante>
    <factura id="comprobante" version="1.0.0">
      <infoTributaria>
        <ambiente>1</ambiente><tipoEmision>1</tipoEmision>
      </infoTributaria>
    </factura>
  </comprobante>    
</autorizacion>

更新1

我认为matthias_h的答案和我的答案是一样的。

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

实际上相当于:

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

实际上相当于:

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

matthias_h的解决方案更明确,使用&#34;逐步&#34;指令,并在需要时允许更精细。