更改节点名称和包装节点

问题描述 投票:0回答:1

我刚开始研究XSLT。我的输入和预期输出如下,XSLT也在下面给出。

我有下一个输入XML:

<servicio>
   <control>
         <codSer>00013</codSer>
         <idMen>12378658936578</idMen>
         <codErr>000</codErr>
         <numId>000xxxxxxxx</numId>
   </control>
   <cuentas>
         <tipPro>3</tipPro>
         <numCta>000000006</numCta>
         <tipCta>A</tipCta>
         <desCta>Cuenta I</desCta>
         <saldo>001513003135</saldo>
   </cuentas>
   <cuentas>
         <tipPro>1</tipPro>
         <numCta>000000005</numCta>
         <tipCta>A</tipCta>
         <desCta>Cuenta I</desCta>
         <saldo>007573144537</saldo>
         <signo>Pos</signo>
   </cuentas>
   <fondos>
         <tipPro>4</tipPro>
         <numCta>000000007</numCta>
         <tipCta>A</tipCta>
         <desCta>Fondo I</desCta>
         <saldo>001513003135</saldo>
   </fondos>
   <fondos>
         <tipPro>4</tipPro>
         <numCta>000000008</numCta>
         <tipCta>A</tipCta>
         <desCta>Fondo I</desCta>
         <saldo>007573144537</saldo>
   </fondos>
</servicio>

我需要应用XSL来获取(输出):

<servicio>
<control>
    <codSer>00013</codSer>
    <idMen>12378658936578</idMen>
    <codErr>000</codErr>
    <numId>000xxxxxxxx</numId>
</control>
<cuentas>
    <cuenta>
        <tipPro>3</tipPro>
        <numCta>000000006</numCta>
        <tipCta>A</tipCta>
        <desCta>Cuenta I</desCta>
        <saldo>001513003135</saldo>
    </cuenta>
    <cuenta>
        <tipPro>1</tipPro>
        <numCta>000000005</numCta>
        <tipCta>A</tipCta>
        <desCta>Cuenta I</desCta>
        <saldo>007573144537</saldo>
        <signo>Pos</signo>
    </cuenta>
</cuentas>
<fondos>
    <fondo>
        <tipPro>4</tipPro>
        <numCta>000000007</numCta>
        <tipCta>A</tipCta>
        <desCta>Fondo I</desCta>
        <saldo>001513003135</saldo>
    </fondo>
    <fondo>
        <tipPro>4</tipPro>
        <numCta>000000008</numCta>
        <tipCta>A</tipCta>
        <desCta>Fondo I</desCta>
        <saldo>007573144537</saldo>
    </fondo>
</fondos>
</servicio>

我尝试过但不起作用的XSL是:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" />
<xsl:strip-space elements="*" />
<xsl:output indent="yes" />
<xsl:param name="elementInfo" select="cuentas,cuentas,cuenta;fondos,fondos,fondo"/>

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

<xsl:template match="node()[name() = name(/*)]">
    <xsl:variable name="inputNode" select="." />
    <xsl:for-each select="tokenize($elementInfo, ';')">
        <xsl:variable name="tokenizedNodeNames" select="tokenize(.,',')" />
        <xsl:for-each select="$inputNode">
            <xsl:call-template name="wrapping">
                <xsl:with-param name="wrapperElementName" select="$tokenizedNodeNames[1]" />
                <xsl:with-param name="oldElementName" select="$tokenizedNodeNames[2]" />
                <xsl:with-param name="newElementName" select="$tokenizedNodeNames[3]" />
            </xsl:call-template>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

<xsl:template name="wrapping">
    <xsl:param name="wrapperElementName" />
    <xsl:param name="oldElementName" />
    <xsl:param name="newElementName" />
    <xsl:copy>
        <xsl:apply-templates select="node()[not(name() = $oldElementName)]" />
        <xsl:element name="{$wrapperElementName}">
            <xsl:for-each select="node()[name() = $oldElementName]">
                <xsl:element name="{$newElementName}">
                    <xsl:copy-of select="@*|node()" />
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

当我输入XML时只有CUENTAS它可以工作,但是当我尝试使用FONDOS时,我正在制作格式错误的XML。

xslt-2.0 tokenize
1个回答
0
投票

我想你只想通过他们的cuentas分组像fondosnode-name()这样的元素:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  exclude-result-prefixes="#all"
  version="2.0">

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

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

<xsl:template match="/*">
  <xsl:copy>
    <xsl:for-each-group select="*" group-by="node-name(.)">
      <xsl:apply-templates select="." mode="wrap"/>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

<xsl:template match="*" mode="wrap">
  <xsl:apply-templates select="current-group()"/>
</xsl:template>

<xsl:template match="cuentas | fondos" mode="wrap">
  <xsl:copy>
    <xsl:apply-templates select="current-group()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="cuentas | fondos">
  <xsl:element name="{substring(local-name(), 1, string-length(local-name()) - 1)}">
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

这样,使用Saxon 9.5,我得到了结果

<servicio>
   <control>
      <codSer>00013</codSer>
      <idMen>12378658936578</idMen>
      <codErr>000</codErr>
      <numId>000xxxxxxxx</numId>
   </control>
   <cuentas>
      <cuenta>
         <tipPro>3</tipPro>
         <numCta>000000006</numCta>
         <tipCta>A</tipCta>
         <desCta>Cuenta I</desCta>
         <saldo>001513003135</saldo>
      </cuenta>
      <cuenta>
         <tipPro>1</tipPro>
         <numCta>000000005</numCta>
         <tipCta>A</tipCta>
         <desCta>Cuenta I</desCta>
         <saldo>007573144537</saldo>
         <signo>Pos</signo>
      </cuenta>
   </cuentas>
   <fondos>
      <fondo>
         <tipPro>4</tipPro>
         <numCta>000000007</numCta>
         <tipCta>A</tipCta>
         <desCta>Fondo I</desCta>
         <saldo>001513003135</saldo>
      </fondo>
      <fondo>
         <tipPro>4</tipPro>
         <numCta>000000008</numCta>
         <tipCta>A</tipCta>
         <desCta>Fondo I</desCta>
         <saldo>007573144537</saldo>
      </fondo>
   </fondos>
</servicio>
© www.soinside.com 2019 - 2024. All rights reserved.