繁体   English   中英

使用xslt从xml删除父节点

[英]Remove parent nodes from xml with xslt

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

输入Xml:

<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>

在xml输出文件中,我只需要节点“ <autorizacion> ”,而无需像这样的“ <mensajes> ”子节点:

所需的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>
        </factura>
    </comprobante>
</autorizacion>

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

Xsl文件:

<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>

这是我通过xsl获得的xml文件:

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:soapxmlns:ns2标记添加到节点<autorizacion><mensajes>节点仍然存在。 请帮助我解决这个问题,如果可能的话,我还需要删除空行,但要保留缩进。

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

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

该模板与任何节点匹配,使用当前匹配的节点的名称创建一个元素,并将模板应用于所有属性和子节点,而无需添加任何名称空间。
要删除空行和空格,可以使用<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>

要在复制时删除名称空间,您只需要说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>

我在身份转换上看到了一些细微变化:

<?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>

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

<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的解决方案使用“逐步”指令更加明确,并在需要时提供更多技巧。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM