Использование XSLT для форматирования XML-файла для ввода в Систему (таблица SQL-сервера) - PullRequest
0 голосов
/ 22 октября 2019

Цель: лаборатория использует устаревший аналитический инструмент, и они хотели бы, чтобы файл экспорта с аналитическими результатами автоматически загружался в нашу систему LIMS. Мы начинаем с грязного XML-файла, который необходимо правильно отформатировать с использованием XSLT.

Начальный XML-файл:

<dataRoot>
  <dataRow>
    <a0>07642110191051151NJL B2019     PURE_ZIN  MLT201910210021               10-21-2019 0840 HRS                                         163111                        029Sn      00000099.5Pb      00000.0163Cu      00000.0111As      00000.0023Bi     &lt;00000.0000Zn      00000.0007Fe      00000.0062Ag      00000.4490Sb      00000.0115Ni      00000.0008Cd      00000.0001S       00000.0007Al      00000.0002Au     &lt;00000.0000P      &lt;00000.0001In      00000.0058Co     &lt;00000.0000Tl      00000.0001Be      0000000000Ce      0000000000Ga      0000000000Ge     &lt;00000.0001Hg      00000.0010Mg      0000000000Pd      0000000000Pt      0000000000Se      0000000000Te      0000000000Bg      00000099.502Customer                                SpecificatBDE                           </a0>
  </dataRow>
  <dataRow>
    <a0>07642110191055181NJL B2019     PURE_ZIN  MLT201910210022               10-21-2019 0920 HRS                                         163111                        029Sn      00000099.5Pb      00000.0197Cu      00000.0104As      00000.0020Bi     &lt;00000.0000Zn      00000.0008Fe      00000.0057Ag      00000.4274Sb      00000.0114Ni      00000.0008Cd      00000.0001S       00000.0007Al      00000.0001Au     &lt;00000.0000P      &lt;00000.0001In      00000.0062Co     &lt;00000.0000Tl      00000.0002Be      0000000000Ce      0000000000Ga      0000000000Ge     &lt;00000.0001Hg      00000.0009Mg      0000000000Pd      0000000000Pt      0000000000Se      0000000000Te      0000000000Bg      00000099.502Customer                                SpecificatBDE                           </a0>
  </dataRow>
</dataRoot>​

Обратите внимание, что последний анализ будет добавлен в тот же файл, поэтомунас интересует только последняя строка для импорта данных.

Что у меня есть для моего XSL-файла, чтобы перевести XML-файл в формат, который я могу ввести в нашу базу данных SQL

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

<xsl:template match="/">
  <!-- Set opening tag to INBOUND -->
  <INBOUND>
        <!-- only process the last row that contains Sample Data (ie: a0 starts with '0'), as the output continually appends new record to existing data -->
        <xsl:for-each select="dataRoot/dataRow[a0][last()]">
            <!-- Get static SAMPLE values that will be the same for all Parameters on a given row -->
            <xsl:variable name="sSampleId" select="normalize-space(substring(a0,41,16))" />
            <xsl:variable name="sText1" select="normalize-space(substring(a0,129,20))" />
            <xsl:variable name="sText6" select="normalize-space(substring(a0,31,10))" />
            <xsl:variable name="sText8" select="normalize-space(substring(a0,71,40))" />
            <xsl:variable name="sSubmitter">OES Import</xsl:variable>           
            <xsl:variable name="dEnteredOn" select="substring(current-date(),0,11)" />
            <xsl:variable name="sEnteredBy">OES Import</xsl:variable>   
            <xsl:variable name="sOwner">MLT</xsl:variable>
            <xsl:variable name="sStringLength" select="string-length(a0)" />
            <xsl:variable name="sDataString" select="substring-before(substring(a0,165,$sStringLength), '02Cust')" />
            <xsl:variable name="sDataStringB" select="translate($sDataString, ' &lt;', '  ')" />
                    <INBOX_SAMPLE>
                        <EVENT>1</EVENT>
                        <SAMPLE_ID>'<xsl:value-of select="$sSampleId" />'</SAMPLE_ID>
                        <TEXT1>'<xsl:value-of select="$sText1" />'</TEXT1>
                        <TEXT6>'<xsl:value-of select="$sText6" />'</TEXT6>
                        <TEXT8>'<xsl:value-of select="$sText8" />'</TEXT8>
                        <SUBMITTER>'<xsl:value-of select="$sSubmitter" />'</SUBMITTER>
                        <ENTERED_ON>'<xsl:value-of select="$dEnteredOn"/>'</ENTERED_ON>
                        <ENTERED_BY>'<xsl:value-of select="$sEnteredBy" />'</ENTERED_BY>    
                        <OWNER>'<xsl:value-of select="$sOwner" />'</OWNER>
                        <STRING_LENGTH>'<xsl:value-of select="$sStringLength" />'</STRING_LENGTH>                                           <DATA_STRING>'<xsl:value-of select="$sDataStringB" />'</DATA_STRING>                
                    </INBOX_SAMPLE>
        </xsl:for-each>
            <!-- get the next record row until there are no more in the file-->
    <!-- closing tag matches opening INBOUND tag -->
    </INBOUND>
</xsl:template>

</xsl:stylesheet>

Что у меня сейчас есть для вывода:

<INBOUND>
   <INBOX_SAMPLE>
      <EVENT>1</EVENT>
      <SAMPLE_ID>'MLT201910210022'</SAMPLE_ID>
      <TEXT1>'163111'</TEXT1>
      <TEXT6>'PURE_ZIN'</TEXT6>
      <TEXT8>'10-21-2019 0920 HRS'</TEXT8>
      <SUBMITTER>'OES Import'</SUBMITTER>
      <ENTERED_ON>'2019-10-22'</ENTERED_ON>
      <ENTERED_BY>'OES Import'</ENTERED_BY>
      <OWNER>'MLT'</OWNER>
      <STRING_LENGTH>'768'</STRING_LENGTH>
      <DATA_STRING>'Sn      00000099.5Pb      00000.0197Cu      00000.0104As      00000.0020Bi      00000.0000Zn      00000.0008Fe      00000.0057Ag      00000.4274Sb      00000.0114Ni      00000.0008Cd      00000.0001S       00000.0007Al      00000.0001Au      00000.0000P       00000.0001In      00000.0062Co      00000.0000Tl      00000.0002Be      0000000000Ce      0000000000Ga      0000000000Ge      00000.0001Hg      00000.0009Mg      0000000000Pd      0000000000Pt      0000000000Se      0000000000Te      0000000000Bg      00000099.5'</DATA_STRING>
   </INBOX_SAMPLE>

Мне нужно, чтобы вместо этой длинной строки «DATA_STRING» каждые 18 символов (после начального ') были бы разбиты ... Это пример, который я сделал вручную, как должен выглядеть конечный результат:

<INBOUND>
   <INBOX_SAMPLE>
      <EVENT>1</EVENT>
      <SAMPLE_ID>'MLT201910210022'</SAMPLE_ID>
      <TEXT1>'163111'</TEXT1>
      <TEXT6>'PURE_ZIN'</TEXT6>
      <TEXT8>'10-21-2019 0920 HRS'</TEXT8>
      <SUBMITTER>'OES Import'</SUBMITTER>
      <ENTERED_ON>'2019-10-22'</ENTERED_ON>
      <ENTERED_BY>'OES Import'</ENTERED_BY>
      <OWNER>'MLT'</OWNER>
      <STRING_LENGTH>'768'</STRING_LENGTH>
      <DATA_STRING>'Sn      00000099.5'</DATA_STRING>
    </INBOX_SAMPLE>
    <INBOX_SAMPLE>
      <EVENT>1</EVENT>
      <SAMPLE_ID>'MLT201910210022'</SAMPLE_ID>
      <TEXT1>'163111'</TEXT1>
      <TEXT6>'PURE_ZIN'</TEXT6>
      <TEXT8>'10-21-2019 0920 HRS'</TEXT8>
      <SUBMITTER>'OES Import'</SUBMITTER>
      <ENTERED_ON>'2019-10-22'</ENTERED_ON>
      <ENTERED_BY>'OES Import'</ENTERED_BY>
      <OWNER>'MLT'</OWNER>
      <STRING_LENGTH>'768'</STRING_LENGTH>
      <DATA_STRING>'Pb      00000.0197'</DATA_STRING>
    </INBOX_SAMPLE>
    <INBOX_SAMPLE>
      <EVENT>1</EVENT>
      <SAMPLE_ID>'MLT201910210022'</SAMPLE_ID>
      <TEXT1>'163111'</TEXT1>
      <TEXT6>'PURE_ZIN'</TEXT6>
      <TEXT8>'10-21-2019 0920 HRS'</TEXT8>
      <SUBMITTER>'OES Import'</SUBMITTER>
      <ENTERED_ON>'2019-10-22'</ENTERED_ON>
      <ENTERED_BY>'OES Import'</ENTERED_BY>
      <OWNER>'MLT'</OWNER>
      <STRING_LENGTH>'768'</STRING_LENGTH>
      <DATA_STRING>'Cu      00000.0104'</DATA_STRING>
    </INBOX_SAMPLE>
    etc.....
</INBOUND>

Длинную строку данных необходимо сначала разбить на более короткие строки длиной 18 символов, а затем цикл for-eachдолжно быть сделано для каждой из этих более коротких подстрок. Я так потерян! Очень стараюсь и могу использовать вашу помощь!

1 Ответ

0 голосов
/ 23 октября 2019

Рассмотрим следующий упрощенный пример:

XSLT 1.0

<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:template match="/dataRoot">
    <xsl:variable name="a0" select="dataRow[last()]/a0" />
    <xsl:variable name="common-nodes">
        <EVENT>1</EVENT>
        <SAMPLE_ID>
            <xsl:value-of select="normalize-space(substring($a0, 41, 16))"/>
        </SAMPLE_ID>
        <TEXT1>
            <xsl:value-of select="normalize-space(substring($a0, 129, 20))"/>
        </TEXT1>
        <!-- add more here ... -->
    </xsl:variable>
    <xsl:variable name="substring" select="substring-before(substring($a0, 165), '02Cust')"/>
    <xsl:variable name="data-string" select="translate($substring, '&lt;', ' ')"/>
    <INBOUND>
        <xsl:call-template name="create-output">
            <xsl:with-param name="string" select="$data-string"/>
            <xsl:with-param name="nodes" select="$common-nodes"/>
        </xsl:call-template>
    </INBOUND>      
</xsl:template>

<xsl:template name="create-output">
    <xsl:param name="string"/>
    <xsl:param name="nodes"/>
    <xsl:param name="len" select="18"/>
    <!-- create node -->
    <INBOX_SAMPLE>
        <xsl:copy-of select="$nodes"/>
        <DATA_STRING>
            <xsl:value-of select="substring($string, 1, $len)"/>
        </DATA_STRING>
    </INBOX_SAMPLE>
    <!-- recursive call -->
    <xsl:if test="string-length($string) > $len">
        <xsl:call-template name="create-output">
            <xsl:with-param name="string" select="substring($string, $len+1)"/>
            <xsl:with-param name="nodes" select="$nodes"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

Применительно к вашему примеру ввода это приведет к:

Результат

<?xml version="1.0" encoding="UTF-8"?>
<INBOUND>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Sn      00000099.5</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Pb      00000.0197</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Cu      00000.0104</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>As      00000.0020</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Bi      00000.0000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Zn      00000.0008</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Fe      00000.0057</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Ag      00000.4274</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Sb      00000.0114</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Ni      00000.0008</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Cd      00000.0001</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>S       00000.0007</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Al      00000.0001</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Au      00000.0000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>P       00000.0001</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>In      00000.0062</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Co      00000.0000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Tl      00000.0002</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Be      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Ce      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Ga      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Ge      00000.0001</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Hg      00000.0009</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Mg      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Pd      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Pt      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Se      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Te      0000000000</DATA_STRING>
  </INBOX_SAMPLE>
  <INBOX_SAMPLE>
    <EVENT>1</EVENT>
    <SAMPLE_ID>MLT201910210022</SAMPLE_ID>
    <TEXT1>163111</TEXT1>
    <DATA_STRING>Bg      00000099.5</DATA_STRING>
  </INBOX_SAMPLE>
</INBOUND>

PS Если это предназначено для обеспечения ввода в базу данных, то вам нужно только добавить уникальный идентификатор для отдельных подстрок,Все остальное следует импортировать один раз в родительскую таблицу, используя отдельный процесс.

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