Генерация идентификаторов для элемента XML с помощью XSLT - PullRequest
0 голосов
/ 18 января 2019

У меня есть 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, чтобы получить следующее (добавление идентификаторов для каждого элемента на основе идентификатора операции и иерархии элементов):

<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 голосов
/ 18 января 2019

Рассмотрим решение 1.0, использующее конкатенацию позиций узлов на ancestor и preceding-sibling:

<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 (расширенный входной XML для более полной демонстрации)

0 голосов
/ 22 января 2019

Наконец-то, получив от вас идеи и немного изменив их, вот что я получил.

Оригинальный 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. последовательность идентификаторов: она рассматривает начальный идентификатор как первый элемент, так что второй идентификатор "original_id.2" вместо "Original_id.1". Кроме того, он не перезапускает последовательность правильно, когда добавление нового элемента (например, 10.5.5 идет после 10.5 вместо 10,1). Тем не менее, он выполняет цель иерархического идентификатора (все числа разные, и вы можете определить, какие элементы отец и сын).

Спасибо всем за помощь!

0 голосов
/ 18 января 2019

Генерация идентификатора верхнего уровня тривиальна:

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

Для более глубоких идентификаторов вы можете использовать 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>

Не проверено, и вам может потребоваться настроить атрибуты xsl: number.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...