2014-09-30 8 views
0

Я пытаюсь объединить 2 xml-файла (как строки в коде).XSL Transformation - Merge elements

<Root> 
    <AMA> 
     <Profile> 
      <UniqueID id="3"/> 
      <Name type="UN">TOTO</Name> 
      <Address>AAA</Address> 
     </Profile> 
     <Profile> 
      <UniqueID id="4"/> 
      <Name>TOTA</Name> 
      <Address>BBB</Address> 
     </Profile> 
     <Profile> 
      <UniqueID id="5"/> 
      <Name>TOTQ</Name> 
     </Profile> 
     <Profile> 
      <UniqueID id="6"/> 
      <Name>TOTG</Name> 
     </Profile> 
     <Profile> 
      <UniqueID id="7"/> 
      <Name>TOTB</Name> 
      <Address>CCC</Address> 
     </Profile> 
    </AMA> 
    <External> 
     <Profile> 
      <UniqueID id="3"/> 
      <Miles>5</Miles> 
     </Profile> 
     <Profile> 
      <UniqueID id="4"/> 
      <Miles>4</Miles> 
<Points>22222</Points> 
     </Profile> 
     <Profile> 
      <UniqueID id="5"/> 
      <Miles>3</Miles> 
     </Profile> 
     <Profile> 
      <UniqueID id="6"/> 
      <Miles>2</Miles> 
     </Profile> 
     <Profile> 
      <UniqueID id="7"/> 
      <Miles>1</Miles> 
     </Profile> 
    </External> 
</Root> 

Я хочу получать

<?xml version="1.0" encoding="ISO-8859-1"?> 
<Root> 
    <Profile> 
     <UniqueID id="3"/> 
     <Name type="UN">TOTO</Name> 
     <Address>AAA</Address> 
     <Miles>5</Miles> 
    </Profile> 
    <Profile> 
     <UniqueID id="4"/> 
     <Name>TOTA</Name> 
     <Address>BBB</Address> 
     <Miles>4</Miles> 
     <Points>22222</Points> 
    </Profile> 
    <Profile> 
     <UniqueID id="5"/> 
     <Name>TOTQ</Name> 
     <Miles>3</Miles> 
    </Profile> 
    <Profile> 
     <UniqueID id="6"/> 
     <Name>TOTG</Name> 
     <Miles>2</Miles> 
    </Profile> 
    <Profile> 
     <UniqueID id="7"/> 
     <Name>TOTB</Name> 
     <Address>CCC</Address> 
     <Miles>1</Miles> 
    </Profile> 
</Root> 

мне удалось написать что-то подобное:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes" /> 
    <Root> 
    <xsl:template match="/Root/AMA/Profile"> 
     <Profile> 
      <xsl:for-each select="."> 
       <xsl:copy-of select="@*|node()"/> 
       <xsl:copy-of select="/Root/External/Profile/UniqueID[@id=current()/UniqueID/@id]/../(Miles|Points)"/> 
      </xsl:for-each> 
     </Profile> 
    </xsl:template> 
    <xsl:template match="/root/External"/> 
</xsl:transform> 
    </Root> 

Как можно избежать "жестко прописывать" узел профиля?

Под «жестко прописывать» Я имею в виду «, чтобы не поставить открытие профиля элемент тега и закрыть мою руку в преобразовании XML, а просто скопировать узел профиля от исходного.

кажется другой способ существует, используя XSLT Lookup Tables и here ... Но, кажется, немного излишним.

как вы думаете, есть лучшее решение?

+0

Можете ли вы уточнить? Что такое «hardcoding the Profile node»? –

+0

Я действительно не уверен, что вы просите. Вы показали нам один входной документ, а не два, которые, как вы говорите, используете, и вы действительно не дали нам подробного объяснения того, что вы хотите сделать слиянием. И я согласен с @KirillPolishchuk, что непонятно, что вы подразумеваете под «hardcoding the Profile node» - что вы хотите сделать, что текущий подход не может сделать? Кроме того, обратите внимание, что ваша таблица стилей плохо сформирована. Элемент Root не имеет правильного гнезда, нет шаблона корневого узла, чтобы начать процесс сопоставления, но поскольку он имеет шаблон, он не является таблицей стилей в стиле pull. Остановите и определите проблему. – keshlam

+0

Да, есть лучшее решение: используйте ** ключ ** для поиска внешних значений. Нет, это не имеет никакого отношения к «* избегать» жесткого кодирования «узла профиля» - эта часть вашего запроса не ясна, как уже отмечали другие. - Обратите внимание также, что '' Ничего не делает. –

ответ

1

похоже, что вы пытаетесь сделать, это объединить Profile детей AMA и External.

Вы чуть были, но вам нужно переместить Root, удалить xsl:for-each и обновить select во втором xsl:copy-of. (Я переместил фиксированный путь к первому xsl:copy-of в моем примере.)

Что-то вроде этого ... (предполагая, что XSLT 2.0 из (Miles|Points) в вашем XPath)

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <!--This will handle <Root/>--> 
    <xsl:template match="/*"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|AMA/Profile"/> 
     </xsl:copy>   
    </xsl:template> 

    <xsl:template match="/Root/AMA/Profile"> 
     <Profile> 
      <xsl:copy-of select="@*|node()| 
      /*/External/Profile[UniqueID/@id=current()/UniqueID/@id]/(Miles|Points)"/> 
     </Profile> 
    </xsl:template> 

</xsl:stylesheet> 

Если вам нужно переключиться на XSLT 1.0, измените значение (Miles|Points) на *[self::Miles or self::Points]

+0

Как насчет того, что Miles и Points находятся во внутреннем элементе Profile, и я хочу держать их на одной глубине? – lucabelluccini

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