2015-08-30 6 views
1

У меня есть xml со значениями partyId и parentPartyId в простой форме. Я хочу преобразовать его в форму иерархического древовидного формата.XSLT для преобразования XML в иерархический формат

Я создал схему в соответствии с желаемым результатом. Я пытаюсь использовать выражения Axis Names в http://www.keller.com/xslt/8/. Я не получаю, как преобразовать источник в желаемый формат?

Источник и требуемая цель:

ИСТОЧНИК:

<OutputCollection xmlns="http://xmlns.test.com/pcbpel/adapter/db/PartyHierarchy"> 
      <Output> 
       <level>1</level> 
       <Parent_Party xsi:nil="true"/> 
       <Party>Party-1</Party> 
      </Output> 
      <Output> 
       <level>2</level> 
       <Parent_Party>Party-1</Parent_Party> 
       <Party>Party-1-1</Party> 
      </Output> 
      <Output> 
       <level>2</level> 
       <Parent_Party>Party-1</Parent_Party> 
       <Party>Party-1-2</Party> 
      </Output> 
      <Output> 
       <level>3</level> 
       <Parent_Party>Party-1-2</Parent_Party> 
       <Party>Party-1-2-1</Party> 
      </Output> 
      <Output> 
       <level>3</level> 
       <Parent_Party>Party-1-2</Parent_Party> 
       <Party>Party-1-2-2</Party> 
      </Output> 
      <Output> 
       <level>3</level> 
       <Parent_Party>Party-1-2</Parent_Party> 
       <Party>Party-1-2-3</Party> 
      </Output> 
      <Output> 
       <level>2</level> 
       <Parent_Party>Party-1</Parent_Party> 
       <Party>Party-1-3</Party> 
      </Output> 
      <Output> 
       <level>3</level> 
       <Parent_Party>Party-1-3</Parent_Party> 
       <Party>Party-1-3-1</Party> 
      </Output> 
      <Output> 
       <level>3</level> 
       <Parent_Party>Party-1-3</Parent_Party> 
       <Party>Party-1-3-2</Party> 
      </Output> 
     </OutputCollection> 

TARGET:

<OutputCollection xmlns="http://xmlns.test.com/pcbpel/adapter/db/PartyHierarchy"> 
      <Output> 
       <level>1</level> 
       <Parent_Party xsi:nil="true"/> 
       <Party>Party-1</Party> 
       <Children> 
        <level>2</level> 
        <Parent_Party>Party-1</Parent_Party> 
        <Party>Party-1-1</Party> 
       </Children> 
       <Children> 
        <level>2</level> 
        <Parent_Party>Party-1</Parent_Party> 
        <Party>Party-1-2</Party> 
        <Children> 
         <level>3</level> 
         <Parent_Party>Party-1-2</Parent_Party> 
         <Party>Party-1-2-1</Party> 
        </Children> 
        <Children> 
         <level>3</level> 
         <Parent_Party>Party-1-2</Parent_Party> 
         <Party>Party-1-2-2</Party> 
        </Children> 
        <Children> 
         <level>3</level> 
         <Parent_Party>Party-1-2</Parent_Party> 
         <Party>Party-1-2-3</Party>     
        </Children> 
       </Children> 
       <Children> 
        <level>2</level> 
        <Parent_Party>Party-1</Parent_Party> 
        <Party>Party-1-3</Party> 
        <Children> 
         <level>3</level> 
         <Parent_Party>Party-1-3</Parent_Party> 
         <Party>Party-1-3-1</Party>     
        </Children> 
        <Children> 
         <level>3</level> 
         <Parent_Party>Party-1-3</Parent_Party> 
         <Party>Party-1-3-2</Party>   
        </Children>     
       </Children> 
      </Output> 
     </OutputCollection> 

ответ

2

С помощью XSLT, если вам необходимо следовать перекрестные ссылки, то вам нужно определить ключевую <xsl:key name="children" match="ph:Output" use="ph:Parent_Party"/> и использовать его <xsl:apply-templates select="key('children', ph:Party)"/>:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ph="http://xmlns.test.com/pcbpel/adapter/db/PartyHierarchy" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://xmlns.test.com/pcbpel/adapter/db/PartyHierarchy" 
    exclude-result-prefixes="ph xsi" 
    version="1.0"> 

<xsl:output indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="children" match="ph:Output" use="ph:Parent_Party"/> 

<xsl:template match="/*"> 
    <xsl:copy> 
    <xsl:apply-templates select="key('children', '')"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="ph:Output[ph:Parent_Party/@xsi:nil = 'true']"> 
    <xsl:copy> 
    <xsl:copy-of select="node()"/> 
    <xsl:apply-templates select="key('children', ph:Party)"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="ph:Output"> 
    <children> 
    <xsl:copy-of select="node()"/> 
    <xsl:apply-templates select="key('children', ph:Party)"/> 
    </children> 
</xsl:template> 

</xsl:stylesheet> 

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

+0

Большое спасибо, Мартин! Я потратил много часов на следующие, предшествующие и т. Д., Но это решение работает и очень кратким. Я новичок в продвинутом XSLT. Можете ли вы предложить любую ссылку на концепции или аналогичные проблемы для практики? –

+0

Существует сборник часто задаваемых вопросов http://www.dpawson.co.uk/xsl/sect2/sect21.html. И вы должны уметь находить подробное объяснение понятий в различных книгах, посвященных XSLT и XPath, которые предлагают издатели. Есть также ресурсы в Интернете по адресу http://www.cranesoftwrights.com/training/index.htm, а страница http://stackoverflow.com/tags/xslt/info также содержит ссылки на онлайн-курсы. –

+0

Спасибо Мартину! Если возможно, можете ли вы показать, как мы можем достичь того же результата, используя имена Axis (а именно: следующий-сиблинг ::, предшествующий и т. Д.). –

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