2015-01-08 3 views
2

Я хочу объединить элементы позиции и создать новый элемент, называемый перемещением, после сравнения атрибута type. Первый тип = "from" должен сливаться с первым типом = "to", и должен продолжаться с остальными.Объединить элементы Xml на основе атрибута с использованием XSLT

ВХОД

<?xml version="1.0" encoding="UTF-8"?> 
<JOB age="0" priority="N"> 
    <container ID="TSTU2345678" TP="4200"/> 
    <container ID="TSTU3456789" TP="4200"/> 
    <position refID="Y.Test:AA.01.01.1" name="AA0101.1" type="from"/> 
    <position refID="Y.Test:AA.01.02.1" name="AA0102.1" type="from"/> 
    <position refID="Y.Test:AA.02.02.1" name="AA0202.1" type="to"/> 
    <position refID="Y.Test:AA.02.03.1" name="AA0203.1" type="to"/> 
</JOB> 

Требуемая мощность

<JOB age="0" priority="N"> 
    <Travel FromrefID="Y.Test:AA.01.01.1" Fromname="AA0101.1" TorefID="Y.Test:AA.02.02.1" Toname="AA0202.1"/> 
    <Travel FromrefID="Y.Test:AA.01.02.1" Fromname="AA0102.1" TorefID="Y.Test:AA.02.03.1" Toname="AA0203.1"/> 
</JOB> 

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="position" match="job/position" use="@type" /> 
    <xsl:template match="job"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*" /> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="/"> 
     <JOB> 
      <xsl:apply-templates select="job/@*" /> 
      <xsl:for-each select="key('position','from')"> 
       <Travel> 
        <xsl:apply-templates select="@*" /> 

        <xsl:for-each select="key('position','to')"> 
         <To> 
          <xsl:apply-templates select="@*" /> 
         </To> 
        </xsl:for-each> 
       </Travel> 

      </xsl:for-each> 
     </JOB> 
    </xsl:template> 

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

</xsl:stylesheet> 

Спасибо.

ответ

3

Я предлагаю вам взглянуть на это следующим образом:

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:key name="to" match="position[@type='to']" use="count(preceding-sibling::position[@type='to'])" /> 

<xsl:template match="/JOB"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:for-each select="position[@type='from']"> 
      <xsl:variable name="to" select="key('to', position() - 1)" /> 
      <Travel FromrefID="{@refID}" Fromname="{@name}" TorefID="{$to/@refID}" Toname="{$to/@name}"/> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

Обратите внимание, что мы предполагаем здесь, что есть равное количество «от» и «до» позиции (или чтобы количество позиций «от» не меньше числа «до» позиций).

1

Альтернативный XSLT 1.0 Раствор

<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="@*|position[@type='from']"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="position[@type='from']"> 
     <xsl:variable name="fromPos" select="position()"/> 
     <Travel FromRefId="{@refID}" Fromname="{@name}"> 
      <xsl:apply-templates select="position[@type='to'][position()=$fromPos]"/> 
     </Travel> 
    </xsl:template> 

    <xsl:template match="position[@type='to']"> 
     <xsl:attribute name="TorefID"> 
      <xsl:value-of select="@refID"/> 
     </xsl:attribute> 
     <xsl:attribute name="Toname"> 
      <xsl:value-of select="@name"/> 
     </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 
Смежные вопросы