XSLT для преобразования xml в xml с извлечением определенных значений и отображением в новый формат

Мне нужна помощь с XSLT для преобразования одного XML-файла в другой формат.

Входной файл xml приведен ниже:

<PATIENTLIST ELAPSEDMS="234" >
    <PATIENT ID="MGH000007">
        <ADDRESS1>550 BREZHNEV ST</ADDRESS1>
        <ADDRESS2></ADDRESS2>
        <CITY>MOSCOW</CITY>
        <STATE>MA</STATE>
        <ZIP>02139</ZIP>
        <COUNTRY ISO3166-1="USSR"></COUNTRY>
        <DATEOFBIRTH>1934/04/10</DATEOFBIRTH>
        <DAYPHONE>(617) 111-1111 </DAYPHONE>
        <FIRSTNAME>TEST</FIRSTNAME>
        <HOMEPHONE>(617) 111-1111</HOMEPHONE>
        <LASTNAME>TEST MGH</LASTNAME>
        <LIMITEDACCESS>False</LIMITEDACCESS>
        <MARITALSTATUS>SINGLE</MARITALSTATUS>
        <MEDICALRECORDNUMBERS>
            <MEDICALRECORDNUMBER>
                <SITE>BWH</SITE>
                <STATUS>A</STATUS>
                <VALUE>0000007</VALUE>
            </MEDICALRECORDNUMBER>
            <MEDICALRECORDNUMBER>
                <SITE>BWI</SITE>
                <STATUS>A</STATUS>
                <VALUE>0000007</VALUE>
            </MEDICALRECORDNUMBER>
            <MEDICALRECORDNUMBER>
                <SITE>MEEI</SITE>
                <STATUS>A</STATUS>
                <VALUE>0000007</VALUE>
            </MEDICALRECORDNUMBER>
            <MEDICALRECORDNUMBER>
                <SITE>MGH</SITE>
                <STATUS>A</STATUS>
                <VALUE>0000007</VALUE>
            </MEDICALRECORDNUMBER>
            <MEDICALRECORDNUMBER>
                <SITE>SHC</SITE>
                <STATUS>A</STATUS>
                <VALUE>0000007</VALUE>
            </MEDICALRECORDNUMBER>
            <MEDICALRECORDNUMBER>
                <SITE>OLD #</SITE>
                <STATUS>M</STATUS>
                <VALUE>0000007</VALUE>
            </MEDICALRECORDNUMBER>
        </MEDICALRECORDNUMBERS>
        <MIDDLEINITIAL>R</MIDDLEINITIAL>
        <MOTHERSMAIDENNAME></MOTHERSMAIDENNAME>
        <MRNR>0000007</MRNR>
        <NAME>TEST MGH, TEST R</NAME>
        <NAMESUFFIX></NAMESUFFIX>
        <NAMEPREFIX></NAMEPREFIX>
        <PRIMARYCAREPROVIDERID>512513</PRIMARYCAREPROVIDERID>
        <PRIMARYLANGUAGE>ENGLISH</PRIMARYLANGUAGE>
        <RACE CODE1="BLACK" CODE2="" FREETEXT="">BLACK</RACE>
        <ETHNICITY CODE1="AFRICAN AMERICAN" CODE2="" FREETEXT="">AFRICAN AMERICAN</ETHNICITY>
        <RELIGION>NO PREFERENCE</RELIGION>
        <SEX>M</SEX>
        <SSN></SSN>
        <UID>101662537</UID>
        <VETERAN>NO</VETERAN>
    </PATIENT>
</PATIENTLIST>

Выходной файл должен выглядеть так:

<?xml version="1.0" encoding="utf-8" ?>
<eCliPSEDataIntegrationServiceRequest xmlns="http://iocent.com/eCliPSEDataIntegrationServiceRequest.xsd">
    <PatientIdentifierRecord MedicalRecordNumber="MGH000007" LastName="Person" FirstName="Test" MiddleInitial="A" DateOfBirth="04/10/1934" Operation="Add" OverwriteExistingData="true" />
    <PatientDataRecord MedicalRecordNumber="MGH000007" ParameterName="Gender" ParameterValue="2" TimeStamp="8/30/2011" Operation="Add" OverwriteExistingData="true" />
    <PatientDataRecord MedicalRecordNumber="MGH000007" ParameterName="Race" ParameterValue="1" TimeStamp="8/30/2011" Operation="Add" OverwriteExistingData="true" />
</eCliPSEDataIntegrationServiceRequest>

Итак, я хочу вытащить

Идентификатор пациента и используйте его в качестве значения MedicalRecordNumber =

Узел DATEOFBIRTH в качестве значения DateOfBirth - с форматом, измененным с ГГГГ / ММ / ДД на ММ / ДД / ГГГГ

Узел FIRSTNAME становится значением для FirstName

Узел LASTNAME становится значением для LastName

Узел MIDDLEINITIAL становится значением для MiddleInitial

Узел SEX становится значением для Gender Male = 1, Female = 2.

Узел RACE становится Value for Race - на основе таблицы поиска (Кавказский = 1, Афинский американец = 2 и т. Д.) -

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

Я ограничен XSLT 1.0

Я очень новичок в XSLT и буду благодарен за любую помощь !!!

Благодарность!


person John Mc    schedule 30.08.2011    source источник
comment
Можете ли вы уточнить узлы Пол и Раса? Их нет в выводе образца.   -  person Emiliano Poggi    schedule 31.08.2011
comment
Да - значение «Пол» взято из узла «Пол» «Раса» из «Расы» в исходном XML-файле.   -  person John Mc    schedule 31.08.2011
comment
тогда ваш образец вывода XML не имеет правильных значений.   -  person Emiliano Poggi    schedule 31.08.2011


Ответы (4)


Я ценю старт, который я получил выше. Я публикую xslt, который я придумал для решения моей проблемы ниже:

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

<xsl:variable name='newline'><xsl:text> 
</xsl:text>
</xsl:variable>

<xsl:variable name='MRN'>
    <xsl:value-of select="PATIENTLIST/PATIENT/@ID"/>
</xsl:variable>

<xsl:variable name='Gender'>
    <xsl:if test="PATIENTLIST/PATIENT/SEX='M'">1</xsl:if>
    <xsl:if test="PATIENTLIST/PATIENT/SEX='F'">2</xsl:if>
</xsl:variable>

 <xsl:variable name='RaceIn'>
   <xsl:value-of select="PATIENTLIST/PATIENT/RACE"/>
 </xsl:variable>  

<xsl:variable name='Race'>
  <xsl:choose>
    <xsl:when test="$RaceIn='WHITE'">1</xsl:when>
    <xsl:when test="$RaceIn='BLACK'">2</xsl:when>
    <xsl:when test="$RaceIn='HISPANIC'">3</xsl:when>
    <xsl:when test="$RaceIn='ASIAN'">4</xsl:when>
    <xsl:when test="$RaceIn='NATIVE AMERICAN'">5</xsl:when>
    <xsl:when test="$RaceIn='INDIAN'">5</xsl:when>
    <xsl:otherwise>7</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

 <xsl:variable name='CurrDate'>
    <xsl:value-of select="'MM/DD/YYY'"/>
</xsl:variable>

<xsl:variable name='Operation'>
    <xsl:value-of select="'Add'"/>
</xsl:variable>

<xsl:variable name='Overwrite'>
    <xsl:value-of select="'true'"/>
</xsl:variable>




  <xsl:template match="/">
    <xsl:text>
    </xsl:text>
      <eCliPSEDataIntegrationServiceRequest >
        <xsl:text>
        </xsl:text>
        <PatientIdentifierRecord>
          <xsl:attribute name="MedicalRecordNumber">
            <xsl:value-of select="$MRN"/>
          </xsl:attribute>
          <xsl:attribute name="LastName">
            <xsl:value-of select="PATIENTLIST/PATIENT/LASTNAME"/>
          </xsl:attribute>
          <xsl:attribute name="FirstName">
            <xsl:value-of select="PATIENTLIST/PATIENT/FIRSTNAME"/>
          </xsl:attribute>
          <xsl:attribute name="MiddleInitial">
            <xsl:value-of select="PATIENTLIST/PATIENT/MIDDLEINITIAL"/>
          </xsl:attribute>
          <xsl:attribute name="DateOfBirth">
            <xsl:value-of select="PATIENTLIST/PATIENT/DATEOFBIRTH"/> <!-- do we need to change the date format?-->
          </xsl:attribute>
          <xsl:attribute name="Operation">
            <xsl:value-of select="$Operation"/>
          </xsl:attribute>
          <xsl:attribute name="OverwriteExistingData">
            <xsl:value-of select="$Overwrite"/>
          </xsl:attribute>
        </PatientIdentifierRecord>
        <xsl:text>
            </xsl:text>
          <PatientDataRecord>
            <xsl:attribute name="MedicalRecordNumber">
              <xsl:value-of select="$MRN"/>
            </xsl:attribute>
            <xsl:attribute name="ParameterName">
              <xsl:value-of select="'Gender'"/>
            </xsl:attribute>
            <xsl:attribute name="ParameterValue">
              <xsl:value-of select="$Gender"/>
            </xsl:attribute>
            <xsl:attribute name="Timestamp">
              <xsl:value-of select="$CurrDate"/>
            </xsl:attribute>
            <xsl:attribute name="Operation">
              <xsl:value-of select="$Operation"/>
            </xsl:attribute>
            <xsl:attribute name="OverwriteExistingData">
              <xsl:value-of select="$Overwrite"/>
            </xsl:attribute>
          </PatientDataRecord>
        <xsl:text>
            </xsl:text>
        <PatientDataRecord>
          <xsl:attribute name="MedicalRecordNumber">
            <xsl:value-of select="$MRN"/>
          </xsl:attribute>
          <xsl:attribute name="ParameterName">
            <xsl:value-of select="'Race'"/>
          </xsl:attribute>
          <xsl:attribute name="ParameterValue">
            <xsl:value-of select="$Race"/>           <!-- this needs to be transformed based on race table and race_7_groups parameter -->
          </xsl:attribute>
          <xsl:attribute name="Timestamp">
            <xsl:value-of select="$CurrDate"/>                  <!-- how do i get the current date?-->
          </xsl:attribute>
          <xsl:attribute name="Operation">
            <xsl:value-of select="$Operation"/>
          </xsl:attribute>
          <xsl:attribute name="OverwriteExistingData">
            <xsl:value-of select="$Overwrite"/>
          </xsl:attribute>
        </PatientDataRecord>
        <xsl:text>
    </xsl:text>
      </eCliPSEDataIntegrationServiceRequest>
  </xsl:template>
</xsl:stylesheet>

Я все еще работаю над решением, чтобы получить текущую дату. Параметры, которые я рассмотрел - передача в качестве параметра - написание функции сценария для получения текущей даты

Кроме того, я еще не уверен, нужно ли мне изменить формат даты с ГГГГ / ММ / ДД на ММ / ДД / ГГГГ.

Если у кого-то есть предложения по двум указанным выше темам, мы будем рады их приветствовать.

Благодарность

person John Mc    schedule 31.08.2011

На основе отзывов - я обновляю свое решение и публикую здесь

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

  <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
  <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

  <xsl:variable name='MRN'>
    <xsl:value-of select="PATIENTLIST/PATIENT/MRNR"/>
  </xsl:variable>

  <xsl:variable name='BirthDate'>
    <xsl:value-of select="PATIENTLIST/PATIENT/DATEOFBIRTH"/>
  </xsl:variable>

  <xsl:variable name="BDayYear" select="substring($BirthDate,1,4)" />
  <xsl:variable name="BDayMonth" select="substring($BirthDate,6,2)" />
  <xsl:variable name="BDayDay" select="substring($BirthDate,9,2)" />

  <xsl:variable name='BirthDateUse'>
    <xsl:value-of select="concat($BDayMonth, '/', $BDayDay, '/', $BDayYear)"/>
  </xsl:variable>

  <xsl:variable name='Gender'>
    <xsl:if test="translate(PATIENTLIST/PATIENT/SEX, $smallcase, $uppercase)='M'">1</xsl:if>
    <xsl:if test="translate(PATIENTLIST/PATIENT/SEX, $smallcase, $uppercase)='F'">2</xsl:if>
  </xsl:variable>

  <xsl:variable name='RaceUC'>
    <xsl:value-of select="translate(PATIENTLIST/PATIENT/RACE, $smallcase, $uppercase)"/>
  </xsl:variable>

  <xsl:variable name='Race'>
    <xsl:choose>
      <xsl:when test="$RaceUC='WHITE'">1</xsl:when>
      <xsl:when test="$RaceUC='BLACK'">2</xsl:when>
      <xsl:when test="$RaceUC='AFRICAN AMERICAN'">2</xsl:when>
      <xsl:when test="$RaceUC='HISPANIC'">3</xsl:when>
      <xsl:when test="$RaceUC='ASIAN'">4</xsl:when>
      <xsl:when test="$RaceUC='NATIVE AMERICAN'">5</xsl:when>
      <xsl:when test="$RaceUC='INDIAN'">6</xsl:when>
      <xsl:otherwise>7</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name='Operation'>
    <xsl:value-of select="'Add'"/>
  </xsl:variable>

  <xsl:variable name='Overwrite'>
    <xsl:value-of select="'true'"/>
  </xsl:variable>

  <xsl:template match="/">
    <eCliPSEDataIntegrationServiceRequest xmlns="http://iocent.com/eCliPSEDataIntegrationServiceRequest.xsd">
      <PatientIdentifierRecord
        MedicalRecordNumber="{$MRN}"
        LastName="{PATIENTLIST/PATIENT/LASTNAME}"
        FirstName="{PATIENTLIST/PATIENT/FIRSTNAME}"
        MiddleInitial="{PATIENTLIST/PATIENT/MIDDLEINITIAL}"
        DateOfBirth ="{$BirthDate}"
        Operation="{$Operation}"
        OverwriteExistingData="{$Overwrite}"
      />
      <PatientDataRecord
          MedicalRecordNumber="{$MRN}"
          ParameterName="Gender" ParameterValue="{$Gender}"
          Operation="{$Operation}"
          OverwriteExistingData="{$Overwrite}"
          />
      <PatientDataRecord
        MedicalRecordNumber="{$MRN}"
        ParameterName="Race_7_Groups" ParameterValue="{$Race}"
        Operation="{$Operation}"
        OverwriteExistingData="{$Overwrite}"
        />
    </eCliPSEDataIntegrationServiceRequest>
  </xsl:template>
</xsl:stylesheet>

Спасибо за отзывы и предложения.

Эта версия обрабатывает преобразование / сравнение регистров, а также форматирование дня рождения в нужном мне формате.

Мне нравится синтаксис AVT для упрощения кода и для удаления «ручного форматирования», которое я делал - спасибо за эти советы!

person John Mc    schedule 02.09.2011
comment
Правильный способ сказать спасибо за полезные ответы - проголосовать за них ;-). В любом случае добро пожаловать. +1 за ваши усилия. - person Emiliano Poggi; 02.09.2011

это должно помочь вам встать на правильный путь:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="PATIENTLIST">
        <xsl:for-each select="PATIENT">                                             
            <eCliPSEDataIntegrationServiceRequest>
                <xsl:attribute name="xmlns">
                    http://iocent.com/eCliPSEDataIntegrationServiceRequest.xsd
                </xsl:attribute>
                <PatientIdentifierRecord>
                    <xsl:attribute name="MedicalRecordNumber">
                        <xsl:value-of select="@ID"/>
                    </xsl:attribute>
                    ...
                    <xsl:for-each select="MEDICALRECORDNUMBER">
                        <xsl:attribute name="MedicalRecordNumber">
                            <xsl:value-of select="@ID"/>
                        </xsl:attribute>
                        ...
                    </xsl:for-each>                                             
                </PatientIdentifierRecord>
            </eCliPSEDataIntegrationServiceRequest>
         </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Вам, вероятно, понадобится несколько жестко закодированных операторов <xsl:if test="SEX='MALE'">1</xsl:if> для переключения "enum"

person Adam Marshall    schedule 30.08.2011
comment
Большое спасибо за то, что начали! Я собираюсь дополнить пост о том, что я создал, чтобы решить эту проблему. - person John Mc; 31.08.2011

Всего несколько подсказок.

Используйте синтаксис AVT, чтобы упростить код. Пример:

    <PatientIdentifierRecord
      MedicalRecordNumber="{$MRN}"
      LastName="{PATIENTLIST/PATIENT/LASTNAME}"
     ...
    />

Для перевода строки используйте код из набора символов ISO-8859-1:

<xsl:variable name="lf" select="'&#10;'"/>

Информацию о дате и времени см. В этой теме. и проверьте документацию по парсеру.

Если вам нужно изменить формат даты, используйте функции substring() и concat(). Проверьте эту похожую тему.

Кажется, что вы используете перевод строки для отступа в коде. Для этого задания у вас есть подходящая инструкция (которая может поддерживаться в зависимости от вашего парсера):

<xsl:output indent="yes"/>
person Emiliano Poggi    schedule 31.08.2011