Возобновление данных в XSLT - PullRequest
       1

Возобновление данных в XSLT

0 голосов
/ 11 октября 2018

У меня есть эти данные XML:

<root>
  (...)
  <items>
    <item>
      (...)
      <custom1>blabla</custom1>
      <custom2>blibli</custom2>
      <custom3>blublu</custom3>
      <custom4/>
      <custom5/>
      <custom6/>
      <custom7/>
      <custom8/>
      <custom9/>
      <custom10/>
      (...)
    </item>
    <item>
      (...)
      <custom1/>
      <custom2/>
      <custom3/>
      <custom4>bloblo</custom1>
      <custom5>bleble</custom2>
      <custom6/>
      <custom7/>
      <custom8/>
      <custom9/>
      <custom10/>
      (...)
    </item>
  </items>
  (...)
</root>

И мне нужно (с XSLT 1.0) преобразовать их в:

<root>
  (...)
  <items>
    <item>
      (...)
      <refVariables>
        <refVariable uuid="var1" value="blabla"/>
        <refVariable uuid="var2" value="blibli"/>
        <refVariable uuid="var3" value="blublu"/>
      </refVariables>
      (...)
    </item>
    <item>
      (...)
      <refVariables>
        <refVariable uuid="var4" value="bloblo"/>
        <refVariable uuid="var5" value="bleble"/>
      </refVariables>
      (...)
    </item>
  </items>
  (...)
  <variables>
    <variable uuid="var1">
      <name>var1</name>
      <comment>Migrated</comment>
    </variable>
    <variable uuid="var2">
      <name>var2</name>
      <comment>Migrated</comment>
    </variable>
    <variable uuid="var3">
      <name>var3</name>
      <comment>Migrated</comment>
    </variable>
    <variable uuid="var4">
      <name>var4</name>
      <comment>Migrated</comment>
    </variable>
    <variable uuid="var5">
      <name>var5</name>
      <comment>Migrated</comment>
    </variable>
  </variables>
</root>

Чтобы возобновить, мне нужно:

  1. преобразование всех узлов в более "общую" форму:
  2. создание всех узлов только для непустых узлов из источника

Первая часть была непростой, но в итоге я нашел решение, которое меня порадовало.

https://pastebin.com/EDkd2ZQu

Но длявторая часть, я понятия не имею, как это сделать, и я не знаю, возможно ли это вообще ...

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

Благодаря Кириллу Полищуку, у которого я позаимствовал «трюк» string(.), который используется для пропуска пустых узлов, вот мое собственное (вероятно, окончательное) решение, которое, кажется, отлично работает:

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

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

    <xsl:variable name="legacy-custom-prefix" select="'custom'"/>

    <!-- A helper to Generate a variable reference for N non empty same customX fields -->
    <xsl:template name="variableGenerator">
        <xsl:param name="nodes"/>
        <xsl:for-each select="$nodes[string(.)][1]">
            <variable uuid="var{substring-after(name(), $legacy-custom-prefix)}">
                <name><xsl:value-of select="concat('var', substring-after(name(), $legacy-custom-prefix))"/></name>
                <comment>Migrated</comment>
            </variable>
        </xsl:for-each>
    </xsl:template>

    <!-- Generate all variables declarations -->
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <variables>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom1"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom2"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom3"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom4"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom5"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom6"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom7"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom8"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom9"/></xsl:call-template>
                <xsl:call-template name="variableGenerator"><xsl:with-param name="nodes" select="//custom10"/></xsl:call-template>
            </variables>
        </xsl:copy>
    </xsl:template>

    <!-- Substitute legacy customX fields by variable references -->
    <xsl:template match="/root/items/item">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
            <refVariables>
                <xsl:for-each select="node()[starts-with(name(), $legacy-custom-prefix)][string(.)]">
                    <xsl:element name="refVariable">
                        <xsl:attribute name="uuid">
                            <xsl:value-of select="concat('var', substring-after(name(.), $legacy-custom-prefix))"/>
                        </xsl:attribute>
                        <xsl:attribute name="value">
                            <xsl:value-of select="node()"/>
                        </xsl:attribute>
                    </xsl:element>
                </xsl:for-each>
            </refVariables>
        </xsl:copy>
    </xsl:template>

    <!-- remove all custom fields for everyone -->
    <xsl:template match="/root/items/item/*[starts-with(name(), 'custom')]"/>
</xsl:stylesheet>
0 голосов
/ 12 октября 2018

Это должно работать:

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

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

  <xsl:template match="items">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>

    <variables>
      <xsl:for-each select="item/*[string(.)]">
        <variable uuid="var{substring-after(name(), 'custom')}">
          <name>
            <xsl:value-of select="concat('var', substring-after(name(), 'custom'))"/>
          </name>
        </variable>
      </xsl:for-each>
    </variables>

  </xsl:template>

  <xsl:template match="item">
    <xsl:copy>
      <refVariables>
        <xsl:apply-templates select="*[string(.)]"/>
      </refVariables>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[starts-with(name(), 'custom')]">
    <refVariable uuid="var{substring-after(name(), 'custom')}" value="{.}" />
  </xsl:template>

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