2012-06-27 6 views
2

У меня есть следующий XML:узлы слияния XML

<Root>  
     <Item> 
      <CityCode>ALV</CityCode> 
      <AirportCode>ALV</AirportCode> 
      <CityName>ANDORRA LA VELLA</CityName> 
      <AirportName>Andorra La Vella Hlpt</AirportName> 
      <StateCode></StateCode> 
      <CountryCode>AD</CountryCode> 
      <AirportTypeCode>8</AirportTypeCode> 
      <AirportTypeName>Heliport, not scheduled</AirportTypeName>  
     </Item>  
</Root> 

и мне нужно, чтобы получить XSLT это:

<Root> 
    <Item> 
    <CityCode>ALV</CityCode> 
    <CityName>ANDORRA LA VELLA</CityName> 
    <CityNameComplete> ANDORRA LA VELLA (ALV) - Andorra La Vella Hlpt </CityNameComplete> 
    <Item> 
<Root> 

Я знаю, как получить первые 2 узла, я не знаю, как «вставить» последнюю.

ответ

0

Вот версия, которая может обрабатывать отсутствующие <AirportCode> и/или <AirportName>:

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

    <!--Identity template. Matches everything that isn't matched 
     by another template and copies it without modification.--> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Item"> 
     <!--Copy the current element (Item) to the output.--> 
     <xsl:copy> 
      <!--Apply templates to attributes of Item and also the 
      CityCode and CityName elements. All other nodes of 
      Item will not be processed.--> 
      <xsl:apply-templates select="CityCode|CityName|@*"/> 
      <CityNameComplete> 
       <!--Output the value of CityName.--> 
       <xsl:value-of select="CityName"/> 
       <!--Apply the template for AirportCode. If it doesn't exist, 
       nothing will be output.--> 
       <xsl:apply-templates select="AirportCode"/> 
       <!--Apply the template for AirportName. If it doesn't exist, 
       nothing will be output.--> 
       <xsl:apply-templates select="AirportName"/> 
      </CityNameComplete> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="AirportCode"> 
     <!--Output the value of AirportCode, surrounded by parenthesis and 
     preceded by a space.--> 
     <xsl:value-of select="concat(' (',.,')')"/> 
    </xsl:template> 

    <xsl:template match="AirportName"> 
     <!--Output the value of AirportName, preceded by a "space dash space".--> 
     <xsl:value-of select="concat(' - ',.)"/> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Где детальное объяснение того, как это работает? Как бы то ни было, этот ответ не очень полезен для будущих посетителей. –

+0

@ O.R.Mapper - код был достаточно прост, я не думал, что это требует подробного объяснения. У ОП не было никаких вопросов, прежде чем принимать ответ, и любой будущий посетитель мог также попросить разъяснений. Я добавил комментарии, чтобы объяснить, что делает код. Если у вас есть конкретный вопрос, на который не распространяются комментарии, сообщите мне. –

+0

Ах, ну, чаще всего одна постоянная Интернета заключается в том, что автор оригинального ответа больше не будет отвечать к тому времени, когда будущий посетитель действительно что-то спросит ;-) Лучше сразу дать объяснения, пока не стало слишком поздно , –

1

Существуют различные способы встраивания этого в ваш полный XSLT, но предположим, что вы рассматриваете элемент <CityNameComplete> в качестве замены элемента <AirportName> из исходного документа Xml.

Затем ключ XSLT в <value-of> элемент:

<xsl:template match="/Root/Item/AirportName"> 
    <CityNameComplete><xsl:value-of select="../CityName"/> (<xsl:value-of select="../AirportCode"/>) - <xsl:value-of select="."/></CityNameComplete> 
</xsl:template> 

Это даст элемент

<CityNameComplete>ANDORRA LA VELLA (ALV) - Andorra La Vella Hlpt</CityNameComplete> 

в результате.

Update: Если вы действительно хотите, чтобы пустое пространство вокруг полное название города, добавьте его <xsl:text> </xsl:text> в таблице стилей:

<xsl:template match="/Root/Item/AirportName"> 
    <CityNameComplete><xsl:text> </xsl:text><xsl:value-of select="../CityName"/> (<xsl:value-of select="../AirportCode"/>) - <xsl:value-of select="."/><xsl:text> </xsl:text></CityNameComplete> 
</xsl:template> 

Результат:

<CityNameComplete> ANDORRA LA VELLA (ALV) - Andorra La Vella Hlpt </CityNameComplete> 

Update 2: Включено код IATA.

Update 3: Альтернативное решение для вставки узла является, чтобы добавить его в шаблон для <Item> элемента:

<xsl:template match="/Root/Item"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     <CityNameComplete><xsl:text> </xsl:text><xsl:value-of select="CityName"/> (<xsl:value-of select="AirportCode"/>) - <xsl:value-of select="AirportName"/><xsl:text> </xsl:text></CityNameComplete> 
    </xsl:copy> 
</xsl:template> 

Заметим, что вы должны удалить узлы, которые вы не хотите точно получите свой результат - поскольку вы этого не просили, и, поскольку я не хотел загромождать ответ, я не включил никакого кода о том, как это сделать.

+0

Thanks, Mapper, он работал идеально! –

+0

Мне удалось удалить узлы, которые мне не нужны, но я не уверен, как сохранить Root и Item. Мой выход заключается в следующем: ALV ла-Велья ла-Велья (ALV) - Андорра-ла-Велья Hlpt

+0

@OanaAnton: Пожалуйста, смотрите пояснения по шаблону идентичности XSLT, например, здесь: http://dev.ektron.com/kb_article.aspx?id=492 Он по существу копирует все содержимое исходного документа Xml на вывод, за исключением узлов, которые сопоставляются с другими шаблонами в вашем XSLT. –

1

Один из способов сделать это, чтобы построить на шаблоне идентичности, и иметь дополнительный шаблон, чтобы соответствовать элемента элемент, в котором вы затем выводить элемент CityNameComplete с помощью Concat функции:

<xsl:template match="Item"> 
    <Item> 
    <xsl:apply-templates select="@*|node()"/> 
    <CityNameComplete> 
     <xsl:value-of select="concat(CityName, ' (', AirportCode, ') ', AirportName)"/> 
    </CityNameComplete> 
    </Item> 
</xsl:template> 

Вам также понадобится шаблон, чтобы игнорировать все элементы, которые вы не хотите выводить.В этом случае все, кроме CityCode и CITYNAME элементы

<xsl:template match="Item/*[not(self::CityCode|self::CityName)]"/> 

Вот полный XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="Item/*[not(self::CityCode|self::CityName)]"/> 

    <xsl:template match="Item"> 
     <Item> 
     <xsl:apply-templates select="@*|node()"/> 
     <CityNameComplete> 
      <xsl:value-of select="concat(CityName, ' (', AirportCode, ') ', AirportName)"/> 
     </CityNameComplete> 
     </Item> 
    </xsl:template> 

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

Применительно к вашей входной XML, следующий выход

<Root> 
    <Item> 
    <CityCode>ALV</CityCode> 
    <CityName>ANDORRA LA VELLA</CityName> 
    <CityNameComplete>ANDORRA LA VELLA (ALV) Andorra La Vella Hlpt</CityNameComplete> 
    </Item> 
</Root> 
+0

+1 для лучшего решения. –

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