使用XSLT生成XML元素的ID

时间:2019-01-18 18:08:13

标签: xml xslt

我有一个具有以下结构的XML文件:

<Operation>
    <id_operation>10</id_operation>
    <operation_type>blablabla</operation_type>
    <Person>
        <surname>Doe</surname>
        <name>John</name>
        <Address>
            <Street>Fake</Street>
            <Number>123</Number>
        </Address>
    </Person>
    <Person>
        <surname>Smith</surname>
        <name>Paul</name>
    </Person>
</Operation>

我需要制作一个XSLT来获得以下内容(根据操作ID和元素层次结构为每个元素添加ID):

<Operation>
    <id>10</id>
    <operation_type>blablabla</operation_type>
    <Person>
        <id>10.1</id>
        <surname>Doe</surname>
        <name>John</name>
        <Address>
            <id>10.1.1</id>
            <Street>Fake</Street>
            <Number>123</Number>
        </Address>
    </Person>
    <Person>
        <id>10.2</id>
        <surname>Smith</surname>
        <name>Paul</name>
    </Person>
</Operation>

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

Generating the top-level id is trivial:

<xsl:template match="id_operation">
  <id><xsl:value-of select="."/></id>
</xsl:template>

For the deeper ids you can use xsl:number:

<xsl:template match="Address">
  <xsl:copy>
    <id>
      <xsl:value-of select="ancestor::operation/id"/>
      <xsl:text>.</xsl:text>
      <xsl:number level="multiple" count="*" from="operation"/>
    </id>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

Not tested and you may need to tweak the xsl:number attributes.

答案 1 :(得分:0)

Consider this 1.0 solution using concatenation of node positions by ancestor and preceding-sibling counts:

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

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

    <xsl:template match="Person">
        <xsl:copy>
            <id><xsl:value-of select="concat('10.', (count(preceding-sibling::*[name()='Person']) + 1))"/></id>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Address">
        <xsl:copy>
            <id><xsl:value-of select="concat('10.', (count(ancestor::Person/preceding-sibling::*[name()='Person']) + 1),
                                             '.', (count(preceding-sibling::*[name()='Address']) + 1))"/></id>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XSLT Demo (extended input XML for fuller demo)

答案 2 :(得分:0)

最后,从您那里获取一些想法并对其进行一些修改,这就是我所得到的。

原始XML:

<Reporte>
    <idoperacion>10</idoperacion>
    <Operacion>
        <Tipo>Lavado</Tipo>
        <Fecha>01/02/2018</Fecha>
    </Operacion>
    <Persona_Fisica>
        <Nombre>Juan</Nombre>
        <Apellido>Perez</Apellido>
        <Domicilio>
            <Calle>Falsa</Calle>
            <Nro>123</Nro>
        </Domicilio>
    </Persona_Fisica>
    <Persona_Juridica>
        <Denominacion>Lavado SRL</Denominacion>
    </Persona_Juridica>
    <Persona_Fisica>
        <Nombre>Jose</Nombre>
        <Apellido>Lopez</Apellido>
        <Tipo_Documento>CUIT</Tipo_Documento>
        <Nro_Documento>12345678</Nro_Documento>
        <Domicilio>
            <Calle>Sarasa</Calle>
            <Nro>1234</Nro>
        </Domicilio>
        <Telefono>
            <Numero>1234-5678</Numero>
        </Telefono>
    </Persona_Fisica>
</Reporte>

XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <!-- Object or Element Property-->
    <xsl:template match="*">
            <xsl:text disable-output-escaping="yes">&lt;</xsl:text>
            <xsl:value-of select="name()"/>
            <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
            <xsl:call-template name="Properties"/>
            <xsl:text disable-output-escaping="yes">&lt;</xsl:text>/<xsl:value-of select="name()"/>
            <xsl:text disable-output-escaping="yes">&gt;</xsl:text>

    </xsl:template>

    <!-- Object Properties -->
    <xsl:template name="Properties">
        <xsl:variable name="childName" select="name(*[1])"/>
        <xsl:choose>
            <xsl:when test="not(*|@*)"><xsl:value-of select="."/></xsl:when>
            <xsl:when test="count(*[name()=$childName]) > 1"><xsl:value-of select="$childName"/>[<xsl:apply-templates select="*" mode="ArrayElement"/>]</xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="@*"/>
                <xsl:apply-templates select="*"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!--ID Reporte-->
    <xsl:template match="idoperacion">
         <id><xsl:value-of select="."/></id>
    </xsl:template>

    <!--ID-->
    <xsl:template match="Operacion | Juzgado | Causa_Penal | Delito | Inmueble | Automotor | Producto | Persona_Fisica | Telefono | Domicilio | Persona_Juridica">
        <xsl:copy>
            <id><xsl:value-of select="ancestor::Reporte/idoperacion"/><xsl:text>.</xsl:text><xsl:number level="multiple" count="*" from="Reporte"/></id>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

新XML:

<Reporte><id>10</id>
<Operacion>
   <id>10.2</id>
        <Tipo>Lavado</Tipo>
        <Fecha>01/02/2018</Fecha>
    </Operacion>
<Persona_Fisica>
   <id>10.3</id>
        <Nombre>Juan</Nombre>
        <Apellido>Perez</Apellido>
        <Domicilio>
      <id>10.3.3</id>
            <Calle>Falsa</Calle>
            <Nro>123</Nro>
        </Domicilio>
    </Persona_Fisica>
<Persona_Juridica>
   <id>10.4</id>
        <Denominacion>Lavado SRL</Denominacion>
    </Persona_Juridica>
<Persona_Fisica>
   <id>10.5</id>
        <Nombre>Jose</Nombre>
        <Apellido>Lopez</Apellido>
        <Tipo_Documento>CUIT</Tipo_Documento>
        <Nro_Documento>12345678</Nro_Documento>
        <Domicilio>
      <id>10.5.5</id>
            <Calle>Sarasa</Calle>
            <Nro>1234</Nro>
        </Domicilio>
        <Telefono>
      <id>10.5.6</id>
            <Numero>1234-5678</Numero>
        </Telefono>
    </Persona_Fisica></Reporte>

这有一些明显的错误:

  1. 缩进:很明显缩进不正确,但事实并非如此 在这一点上很重要。
  2. ID序列:正在将初始ID视为 第一个元素,因此第二个ID为“ original_id.2”,而不是 “ original_id.1”。另外,当 添加一个新元素(例如,10.5.5在10.5之后而不是 10.1)。但是,它实现了层次结构ID的目标(所有数字都是不同的,您可以确定哪些元素是 父亲和儿子)。

感谢您的帮助!