E
E
eliasum2022-01-13 14:24:21
XSL & XSLT
eliasum, 2022-01-13 14:24:21

How to fix xsl style file?

There is an xml file:

<Station  >
  <Equip   key="_key">
    <Mode  >
      <Item key="Auto"  >
        <Command  >
          <Item key="Run"   />
          <Item key="Break"   />
          <Item key="Pause"   />
          <Item key="Continue"   />
        </Command>
      </Item>
      <Item key="Manual"   />
    </Mode>
    <Command  >
      <Item key="Run"   />
      <Item key="Break"   />
      <Item key="Pause"   />
      <Item key="Continue"   />
    </Command>
    <Slot  >
      <Item key="1"  >
        <Mode  >
          <Item key="Auto"  >
            <Command  >
              <Item key="Run"   />
              <Item key="Break"   />
              <Item key="Pause"   />
              <Item key="Continue"   />
            </Command>
          </Item>
          <Item key="Manual"   />
        </Mode>
        <Product  >
          <SerialNumber   value="" />
          <Info   value="" />
        </Product>
        <Supply  >
          <Item key="Ph"  >
            <Amperage   symbol="I" unit="[А]" format="F1" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Amperage>
            <Voltage   symbol="U" unit="[В]" format="N0" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Voltage>
          </Item>
          <Item key="Mc1"  >
            <Amperage   symbol="I" unit="[А]" format="F1" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Amperage>
            <Voltage   symbol="U" unit="[В]" format="N0" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Voltage>
          </Item>
          <Item key="Mc12"  >
            <Amperage   symbol="I" unit="[А]" format="F1" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Amperage>
            <Voltage   symbol="U" unit="[В]" format="N0" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Voltage>
          </Item>
          <Item key="Mc2"  >
            <Amperage   symbol="I" unit="[А]" format="F1" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Amperage>
            <Voltage   symbol="U" unit="[В]" format="N0" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Voltage>
          </Item>
          <Item key="An"  >
            <Amperage   symbol="I" unit="[А]" format="F1" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Amperage>
            <Voltage   symbol="U" unit="[В]" format="N0" value="">
              <Allowance   symbol="Δ" unit="[%]" value="3" />
            </Voltage>
          </Item>
        </Supply>
        <Command  >
          <Item key="Run"   />
          <Item key="Break"   />
          <Item key="Pause"   />
          <Item key="Continue"   />
        </Command>
      </Item>
    </Slot>
    <Chart   />
  </Equip>
</Station>


From which using the xsl style file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8"/>
  <xsl:variable name="apostrophe">'</xsl:variable>
  <xsl:template match="/">
<xsl:text>
CREATE TABLE table (
    key integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
    config text NOT NULL,
    allowance float NOT NULL,
    tablename character(15) NOT NULL,
    CONSTRAINT "table_key" PRIMARY KEY (key)
);

INSERT INTO table (config, allowance, tablename) VALUES 
</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>;</xsl:text>
  </xsl:template>
  
  <xsl:template match="node()[@format]">
    <xsl:variable name="allowance" select="Allowance/@value"/>
    <xsl:value-of select="concat('(', $apostrophe)"/>
    <xsl:for-each select="ancestor::*">
      <xsl:variable name="element" select="local-name()"/>
      <xsl:value-of select="$element"/>
      <xsl:if test="$element='Item'">
        <xsl:value-of select="concat('[@key=', $apostrophe, $apostrophe, @key, $apostrophe, $apostrophe, ']')"/>
      </xsl:if>
      <xsl:text>/</xsl:text>
    </xsl:for-each>
    <xsl:choose>
      <xsl:when test="starts-with(@format, 'N')">
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'number_actual', $apostrophe, '),')"/>
      </xsl:when>
      <xsl:when test="starts-with(@format, 'F')">
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'float_actual', $apostrophe, '),')"/>
      </xsl:when>
      <xsl:when test="starts-with(@format, 'D')">
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'decimal_actual', $apostrophe, '),')"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'string_actual', $apostrophe, '),')"/>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>


sql script is generated:
CREATE TABLE table (
    key integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
    config text NOT NULL,
    allowance float NOT NULL,
    tablename character(15) NOT NULL,
    CONSTRAINT "table_key" PRIMARY KEY (key)
);

INSERT INTO table (config, allowance, tablename) VALUES 
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Ph'']/Amperage', 3, 'float_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Ph'']/Voltage', 3, 'number_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc1'']/Amperage', 3, 'float_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc1'']/Voltage', 3, 'number_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc12'']/Amperage', 3, 'float_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc12'']/Voltage', 3, 'number_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc2'']/Amperage', 3, 'float_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc2'']/Voltage', 3, 'number_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''An'']/Amperage', 3, 'float_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''An'']/Voltage', 3, 'number_actual'),
;


The sql script has an extra comma at the very end, and a semicolon from a new line, which is why the script is not working until you fix it manually. How to rewrite the xsl style file so that at the end of the sql script the code is generated correctly automatically:
...
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc2'']/Voltage', 3, 'number_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''An'']/Amperage', 3, 'float_actual'),
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''An'']/Voltage', 3, 'number_actual');

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
alexalexes, 2022-01-13
@eliasum

Сложно сделать first- или last- специфичный выходной элемент, так как нельзя внятно получить значение position.
Однако, можно воспользоваться таким костылем:
1) Вывести запятую и перенос строки впереди очередного элемента VALUES, сохранив перенос после элемента.
2) Закомментировать лишнюю запятую в запросе.
То есть добиться такого вывода:

INSERT INTO table (config, allowance, tablename) VALUES --,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Ph'']/Amperage', 3, 'float_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Ph'']/Voltage', 3, 'number_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc1'']/Amperage', 3, 'float_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc1'']/Voltage', 3, 'number_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc12'']/Amperage', 3, 'float_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc12'']/Voltage', 3, 'number_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc2'']/Amperage', 3, 'float_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''Mc2'']/Voltage', 3, 'number_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''An'']/Amperage', 3, 'float_actual')
,
('Station/Equip/Slot/Item[@key=''1'']/Supply/Item[@key=''An'']/Voltage', 3, 'number_actual')
;

Правило:
INSERT INTO table (config, allowance, tablename) VALUES --</xsl:text><xsl:apply-templates/>
    <xsl:text>;</xsl:text>
  </xsl:template>
  
  <xsl:template match="node()[@format]">
    <xsl:variable name="allowance" select="Allowance/@value"/>
   <xsl:text>,&#10;</xsl:text> <!-- Сюда добавлены запятая и перенос -->    
<xsl:value-of select="concat('(', $apostrophe)"/>
    <xsl:for-each select="ancestor::*">
      <xsl:variable name="element" select="local-name()"/>
      <xsl:value-of select="$element"/>
      <xsl:if test="$element='Item'">
        <xsl:value-of select="concat('[@key=', $apostrophe, $apostrophe, @key, $apostrophe, $apostrophe, ']')"/>
      </xsl:if>
      <xsl:text>/</xsl:text>
    </xsl:for-each>
    <xsl:choose>
      <xsl:when test="starts-with(@format, 'N')">
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'number_actual', $apostrophe, ')')"/> <!--убран вывод последней запятой -->
      </xsl:when>
      <xsl:when test="starts-with(@format, 'F')">
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'float_actual', $apostrophe, ')')"/> <!--убран вывод последней запятой -->
      </xsl:when>
      <xsl:when test="starts-with(@format, 'D')">
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'decimal_actual', $apostrophe, ')')"/> <!--убран вывод последней запятой -->
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat(local-name(), $apostrophe, ', ', $allowance, ', ', $apostrophe, 'string_actual', $apostrophe, ')')"/> <!--убран вывод последней запятой -->
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question