2013-02-26 6 views
0

Хорошо, я редактирую исходное сообщение. Думаю, я немного потрудился, заменив теги имен исходного XML. В любом случае, вот выдержка из оригинального файла:нужна помощь в преобразовании XML в XML с использованием XSL

<EMPLOYEE_LIST> 
    <EMPLOYEES> 
     <EMPLOYEE> 
     <EMPID>650000</EMPID> 
     <FIRST_NAME>KEITH</FIRST_NAME> 
     <MIDDLE_NAME>HUTCHINSON</MIDDLE_NAME> 
     <LAST_NAME>ROGERS</LAST_NAME> 
     <EMP_TYPE></EMP_TYPE> 
     <EMP_REF_ID>500000</EMP_REF_ID> 
     <JOINED_ON>2001-10-06</JOINED_ON> 
     <COMMENTS>Miscellanous Comments</COMMENTS> 
     <NATIONALITY> 
      <VALUE>American</VALUE> 
     </NATIONALITY> 
     <EMP_AKA> 
      <AKA_NAME>Danny</AKA_NAME> 
     </EMP_AKA> 
     <EMP_AKA> 
      <AKA_NAME>Dan</AKANAME> 
     </EMP_AKA> 
     <EMP_AKA> 
      <AKA_NAME>Ray</AKA_NAME> 
     </EMP_AKA> 
     <EMP_ADDR> 
      <STREET> </STREET> 
      <CITY> </CITY> 
      <STATE> </STATE> 
      <ZIP> </ZIP> 
      <COUNTRY> </COUNTRY> 
     </EMPLOYEE> 
    </EMPLOYEES> 
</EMPLOYEE_LIST> 

Вопрос, который я столкнулся с выше XML является то, что я не могу найти способ, чтобы соответствовать несколько AKA (Also Known As) атрибуты под одной собственности и XSL, что я использую для этого преобразования заключается в следующем:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 
     <xsl:template match="/EMPLOYEE_LIST"> 
      <employees> 
       <xsl:apply-templates select="EMPLOYEES/node()"/> 
      </employees>   
     </xsl:template> 

     <xsl:template match="EMPLOYEE"> 
     <employee> 
      <xsl:apply-templates select="*"/> 
     </employee> 
     </xsl:template> 

     xsl:template match="EMPLOYEE/EMPID"> 
     <emp_id> 
      <xsl:value-of select="."/> 
     </emp_id> 
     </xsl:template> 

      <xsl:template match="EMPLOYEE/FIRST_NAME"> 
     <f_name> 
      <xsl:value-of select="."/> 
     </f_name> 
     </xsl:template> 

     <xsl:template match="EMPLOYEE/MIDDLE_NAME"> 
      <m_name> 
       <xsl:value-of select="."/> 
      </m_name> 
     </xsl:template> 

     <xsl:template match="EMPLOYEE/LAST_NAME"> 
      <l_name> 
       <xsl:value-of select="."/> 
      </l_name> 
     </xsl:template> 
     . 
     . 
     . 
     . 
     . 
     <xsl:template match="EMPLOYEE/EMP_AKA"> 
     <aka_list> 
      <xsl:for-each select="AKA_NAME"> 
       <aka> 
        <xsl:for-each select="."> 
         <xsl:apply-templates/> 
        </xsl:for-each> 
       </aka> 
      </xsl:for-each> 
     </aka_list> 
    </xsl:template> 
</xsl:stylesheet> 

Вышеприведенный XSL применительно к моему XML дает следующий вывод:

<?xml version="1.0" encoding="UTF-8"?> 
<employees> 
     <employee> 
     <emp_id>111345</emp_id> 
     <f_name>KEITH</f_name> 
     <m_name>HUTCHINSON</m_name> 
     <l_name>ROGERS</l_name> 
     <aka_list> 
      <aka>Danny</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Dan</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Ray</aka> 
     </aka_list> 
     </employee> 
</employees> 

который не то, что я т чтобы получить, так как мне нужны данные в следующем формате:

<?xml version="1.0" encoding="UTF-8"?> 
<employees> 
     <employee> 
     <emp_id>111345</emp_id> 
     <f_name>KEITH</f_name> 
     <m_name>HUTCHINSON</m_name> 
     <l_name>ROGERS</l_name> 
     <aka_list> 
      <aka>Danny</aka> 
      <aka>Dan</aka> 
      <aka>Ray</aka> 
     </aka_list> 
     </employee> 
</employees 

Есть ли способ достичь этого?

Двигаясь вперед, есть элементы в XML, которые находятся в огромных количествах, например, AKA_NAME.

  <aka_list> 
      <aka>Danny</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Dan</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Ray</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Danny_2</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Dan_2</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Ray_2</aka> 
     </aka_list> 

Преобразование должно нести только вперед верхнюю 5 и шестой следует быть усечены, как:

  <aka_list> 
      <aka>Danny</aka> 
      <aka>Dan</aka> 
      <aka>Ray</aka> 
      <aka>Danny_2</aka> 
      <aka>Dan_2</aka> 
     </aka_list> 
+0

Выведенный вами результат не соответствует шаблону XSLT (на выходе нет элемента AKA_LIST). –

+0

' JOHN FILTER' открывается с закрытием AKA с ALIAS, ошибка проверки. Будьте уверены, что ваш входной XML. –

+0

Я не понимаю, у вас есть '' в вашем коде, но '' и' 'в вашем выпуске ?? То, что вы хотите? –

ответ

2

UPDATE: решение для полного XML.

Я попытался объяснить решение, используя комментарии в шаблоне XSLT.

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

    <!-- Ignore text nodes by default --> 
    <xsl:template match="text()" /> 

    <!-- Transform tag name EMPLOYEES to employees --> 
    <xsl:template match="EMPLOYEES"> 
     <employees> 
      <xsl:apply-templates select="*" /> 
     </employees> 
    </xsl:template> 

    <!-- Transform tag name EMPLOYEE to employee --> 
    <xsl:template match="EMPLOYEE"> 
     <employee> 
      <xsl:apply-templates select="*" /> 
     </employee> 
    </xsl:template> 

    <!-- Transform tag name EMPID to emp_id --> 
    <xsl:template match="EMPID"> 
     <emp_id> 
      <xsl:value-of select="." /> 
     </emp_id> 
    </xsl:template> 

    <!-- Transform tag name FIRST_NAME to f_name --> 
    <xsl:template match="FIRST_NAME"> 
     <f_name> 
      <xsl:value-of select="." /> 
     </f_name> 
    </xsl:template> 

    <!-- Transform tag name MIDDLE_NAME to m_name --> 
    <xsl:template match="MIDDLE_NAME"> 
     <m_name> 
      <xsl:value-of select="." /> 
     </m_name> 
    </xsl:template> 

    <!-- Transform tag name LAST_NAME to l_name --> 
    <xsl:template match="LAST_NAME"> 
     <l_name> 
      <xsl:value-of select="." /> 
     </l_name> 
    </xsl:template> 

    <!-- When encounter the first EMP_AKA element, print itself and its following 
     siblings with the same name within an aka_list element --> 
    <xsl:template match="EMP_AKA[1]"> 
     <aka_list> 
      <xsl:apply-templates select="AKA_NAME|following-sibling::EMP_AKA/AKA_NAME" mode="print"/> 
     </aka_list> 
    </xsl:template> 

    <!-- Transform tag name EMP_AKA to aka --> 
    <xsl:template match="AKA_NAME" mode="print"> 
     <aka> 
      <xsl:value-of select="." /> 
     </aka> 
    </xsl:template> 

</xsl:stylesheet> 

UPDATE 2: В случае, если вы не хотите использовать режимы шаблона, поскольку AKA_NAME собирается быть согласованы в другом месте и обрабатываются таким же образом, вы можете заменить последние два шаблона этих единиц :

<!-- When encounter the first EMP_AKA element, print itself and its following 
    siblings with the same name within an aka_list element --> 
<xsl:template match="EMP_AKA[1]"> 
    <aka_list> 
     <xsl:apply-templates select="AKA_NAME|following-sibling::EMP_AKA/AKA_NAME" /> 
    </aka_list> 
</xsl:template> 

<!-- Exclude all EMP_AKA elements (except the first one because 
    the previous template has higher precedence than this one) --> 
<xsl:template match="EMP_AKA" /> 

<!-- Transform tag name EMP_AKA to aka --> 
<xsl:template match="AKA_NAME"> 
    <aka> 
     <xsl:value-of select="." /> 
    </aka> 
</xsl:template> 

<xsl:template match="EMP_AKA" /> 

Этот код производит тот же результат, что и предыдущий.


UPDATE 3: OP задан вопрос о том, как ограничить количество AKA_NAME элементов, выводимых. Это решение основано на UPDATE 2. Просто замените последние шаблоны из UPDATE 2 с

<xsl:template match="EMP_AKA[1]"> 
    <aka_list> 
     <xsl:apply-templates select="AKA_NAME|following-sibling::EMP_AKA[position() &lt; 5]/AKA_NAME" /> 
    </aka_list> 
</xsl:template> 

<!-- Transform tag name EMP_AKA to aka --> 
<xsl:template match="AKA_NAME"> 
    <aka> 
     <xsl:value-of select="." /> 
    </aka> 
</xsl:template> 

<xsl:template match="EMP_AKA" /> 

оригинального ответом

ОП отредактированный пост и полностью изменил файл XML. Следующим был мой предыдущий ответ (похоже, не удавалось удалить его).

Если вы пытаетесь сгруппировать все AKA> элементы < в элемент с < AKA_LIST> (не ясно, потому что вывод, что вы вывесили не соответствует преобразование), то вы можете использовать следующее преобразование:

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

    <!-- Just for demo --> 
    <xsl:template match="text()" /> 

    <!-- Match PERSON: create the list --> 
    <xsl:template match="PERSON"> 
     <AKA_LIST> 
      <xsl:apply-templates select="NAME/AKA" /> 
     </AKA_LIST> 
    </xsl:template> 

    <!-- Outputs the AKA element, changing the tag name --> 
    <xsl:template match="AKA"> 
     <aka> 
      <xsl:value-of select="." /> 
     </aka> 
    </xsl:template> 

</xsl:stylesheet> 

Какой превратить вас источник XML в:

<AKA_LIST> 
    <aka>ROSE PETAL</aka> 
    <aka>JOHN FILTER</aka> 
</AKA_LIST> 
+0

приятное решение Pablo, только с использованием совпадений шаблонов и шаблонов приложений. +1 – Peter

+0

'' не требуется .. coz это не требование переименовать .. Также лучше было бы переопределить шаблон идентификации .. –

+0

Ну, мы не будем знать, что пока ОП не разъяснит в своем посте, что он пытается сделать. Я сделал предположение о том, что он пытается сделать, и я опубликовал решение для этого. Я не думаю, что мы можем предположить, что это так, или это не требование переименовать (представьте, что после этого он будет использовать XML-схему для проверки выходного XML). –

1

Ваш код XSLT фактически путает, потому что у вас есть какие-то теги, как <AKA_LIST>. Так что я иду на входных и выходных XML образцов: здесь код XSLT

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

    <xsl:template match="PERSON"> 
    <xsl:copy> 
     <xsl:apply-templates select="NAME[1]"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="NAME"> 
    <xsl:copy> 
     <xsl:apply-templates select="/PEOPLE/PERSON/NAME/AKA"/> 
    </xsl:copy> 
    </xsl:template> 


</xsl:stylesheet> 

Входной XML:

<?xml version="1.0" encoding="utf-8"?> 
<PEOPLE> 
    <PERSON> 
    <NAME> 
     <REFERENCE>GOOD</REFERENCE> 
     <AKA>ROSE PETAL</AKA> 
     </NAME> 
    <NAME> 
     <REFERENCE>GOOD</REFERENCE> 
     <AKA>JOHN FILTER</AKA> 
     </NAME> 
    </PERSON> 
</PEOPLE> 

Выход:

<?xml version="1.0" encoding="utf-8"?> 
<PEOPLE> 
    <PERSON> 
    <NAME> 
     <AKA>ROSE PETAL</AKA> 
     <AKA>JOHN FILTER</AKA> 
    </NAME> 
    </PERSON> 
</PEOPLE> 

Объяснение:

<xsl:template match="@*|node()"> ...... 

приведенных выше код копирует теги от входа к выходу AS IS *, Другой матч шаблона переопределить ..

<xsl:template match="PERSON"> ...... 

вышеприведенного код копирует только ОДИН <NAME> TAG (первый) в выходной ..

<xsl:template match="NAME"> 
    <xsl:copy> 
     <xsl:apply-templates select="/PEOPLE/PERSON/NAME/AKA"/> 
     ...... 

выше код копирует все<AKA>теги под<NAME>. Поскольку мы копируем только один тег <NAME>, все теги <AKA> отображаются под <NAME>.

Смежные вопросы