2012-06-20 2 views
2

Как я могу справиться с этим, чтобы concate подобные XML-теги в XML-файлеConcate Подобные тегов XML Значения с XSLT

У меня есть XML в следующем формате ::

<addressbook> 
<address> 
    <first-name>Chester Hasbrouck</first-name> 
    <Descritpion>Hi</Descritpion> 
    <Descritpion>This is Chester </Descritpion> 
    <street>1234 Main Street</street> 
    <city>Sheboygan</city> 
    <state>WI</state> 
    <zip>48392</zip> 
</address> 
<address> 
    <first-name>Mary</first-name> 
    <Descritpion>Hi</Descritpion> 
    <Descritpion>This is Mary </Descritpion> 
    <Descritpion>Bye</Descritpion> 
    <street>283 First Avenue</street> 
    <city>Skunk Haven</city> 
    <state>MA</state> 
    <zip>02718</zip> 
</address> 
</addressbook> 

мне это нужно в следующем формате кого-то предложите XSLT для этого.

<addressbook> 
<address> 
    <first-name>Chester Hasbrouck</first-name> 
    <Descritpion>Hi | This is Chester </Descritpion> 
    <street>1234 Main Street</street> 
    <city>Sheboygan</city> 
    <state>WI</state> 
    <zip>48392</zip> 
</address> 
<address> 
    <first-name>Mary</first-name> 
    <Descritpion>Hi | This is Mary | Bye</Descritpion> 
    <street>283 First Avenue</street> 
    <city>Skunk Haven</city> 
    <state>MA</state> 
    <zip>02718</zip> 
</address> 
</addressbook> 
+0

Будут ли похожие имена тегов быть смежными или будут случаи разного имени тега. Например, ' Hi Bye' –

+0

Спасибо, похожие тэги всегда Соседние –

+0

? Это типографская ошибка? –

ответ

0

Чтобы сделать это, вы можете построить на тождественное преобразование, но добавить в дополнительных правил для обработки элементов вы заинтересованы в

Я думаю, вам в первую очередь необходимо, чтобы соответствовать элементы, которые не имеют детей элементы в них

<xsl:template match="*[not(*)]" priority="1"> 

Вы бы затем добавить код к этому выводить текущее значение текста, а затем выберите текстовое значение всех следующих братьев и сестер с таким же названием (который будет выводиться с разделителем перед ними)

<xsl:apply-templates 
    select="following-sibling::*[local-name() = local-name(current())]/text()" 
    mode="concat"/> 

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

<xsl:template 
    match="*[not(*)][local-name() = local-name(preceding-sibling::*[1])]" 
    priority="2" /> 

Обратите внимание на использовании приоритета атрибута здесь, так что процессор XSLT совпадает с первым с более высоким приоритетом.

Вот полный XSLT

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

    <xsl:template match="*[not(*)]" priority="1"> 
     <xsl:copy> 
     <xsl:value-of select="normalize-space(.)"/> 
     <xsl:apply-templates select="following-sibling::*[local-name() = local-name(current())]/text()" mode="concat"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*[not(*)][local-name() = local-name(preceding-sibling::*[1])]" priority="2"/> 

    <xsl:template match="text()" mode="concat"> 
     <xsl:value-of select="concat(' | ', normalize-space(.))"/> 
    </xsl:template> 

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

При нанесении на ваш образец XML, следующий выход

<addressbook> 
    <address> 
     <first-name>Chester Hasbrouck</first-name> 
     <Descritpion>Hi | This is Chester</Descritpion> 
     <street>1234 Main Street</street> 
     <city>Sheboygan</city> 
     <state>WI</state> 
     <zip>48392</zip> 
    </address> 
    <address> 
     <first-name>Mary</first-name> 
     <Descritpion>Hi | This is Mary | Bye</Descritpion> 
     <street>283 First Avenue</street> 
     <city>Skunk Haven</city> 
     <state>MA</state> 
     <zip>02718</zip> 
    </address> 
</addressbook> 
1

Это преобразование:

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

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

<xsl:template match="Descritpion[not(preceding-sibling::*[1][self::Descritpion])]"> 
    <Descritpion> 
    <xsl:value-of select="."/> 
    <xsl:apply-templates select="following-sibling::Descritpion/text()"/> 
    </Descritpion> 
</xsl:template> 

<xsl:template match="Descritpion/text()"> 
    <xsl:value-of select="concat(' | ', .)"/> 
</xsl:template> 
<xsl:template match="Descritpion"/> 
</xsl:stylesheet> 

при нанесении на предоставленный XML-документ ument:

<addressbook> 
    <address> 
     <first-name>Chester Hasbrouck</first-name> 
     <Descritpion>Hi</Descritpion> 
     <Descritpion>This is Chester </Descritpion> 
     <street>1234 Main Street</street> 
     <city>Sheboygan</city> 
     <state>WI</state> 
     <zip>48392</zip> 
    </address> 
    <address> 
     <first-name>Mary</first-name> 
     <Descritpion>Hi</Descritpion> 
     <Descritpion>This is Mary </Descritpion> 
     <Descritpion>Bye</Descritpion> 
     <street>283 First Avenue</street> 
     <city>Skunk Haven</city> 
     <state>MA</state> 
     <zip>02718</zip> 
    </address> 
</addressbook> 

производит разыскиваемого, правильный результат:

<addressbook> 
    <address> 
     <first-name>Chester Hasbrouck</first-name> 
     <Descritpion>Hi | This is Chester </Descritpion> 
     <street>1234 Main Street</street> 
     <city>Sheboygan</city> 
     <state>WI</state> 
     <zip>48392</zip> 
    </address> 
    <address> 
     <first-name>Mary</first-name> 
     <Descritpion>Hi | This is Mary | Bye</Descritpion> 
     <street>283 First Avenue</street> 
     <city>Skunk Haven</city> 
     <state>MA</state> 
     <zip>02718</zip> 
    </address> 
</addressbook> 

Объяснение:

  1. Идентичность копирует правило каждый узел "как есть".

  2. Descritpion элементы, как правило, игнорируются/удаляются путем переопределения шаблона идентификации с использованием шаблона с нулевым состоянием, соответствующего Descritpion.

  3. Элемент Descritpion, который непосредственно предшествует родственному элементу не является самим Descritpion, обрабатывается специально другим шаблоном переопределения.Здесь строковое значение элемента копируется, а затем шаблоны применяются ко всем текстовым узлам-дочерним элементам следующих элементов: Descritpion.

  4. Шаблон, соответствующий текстовому узлу-потомку элемента Descritpion, реализует требуемую конкатенацию текста.

0

Вот еще один способ сделать это.

Одно замечание: это решение не поддерживать порядок вывода документа (то есть, он не создает новый <Descritpion> элемент непосредственно под <first-name> элемента). Если это важно для вас, взгляните на другие предоставленные решения.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output omit-xml-declaration="no" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <!-- TEMPLATE #2 --> 
    <xsl:template match="address"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
     <Descritpion> 
     <xsl:apply-templates select="Descritpion/text()"/> 
     </Descritpion> 
    </xsl:copy> 
    </xsl:template> 

    <!-- TEMPLATE #3 --> 
    <xsl:template match="Descritpion/text()"> 
    <xsl:value-of select="." /> 
    <xsl:if test="position() != last()"> | </xsl:if>  
    </xsl:template> 

    <!-- TEMPLATE #4 --> 
    <xsl:template match="Descritpion" /> 
</xsl:stylesheet> 

Когда это предусмотрено на прилагаемом документе XML:

<?xml version="1.0" encoding="UTF-8"?> 
<addressbook> 
    <address> 
    <first-name>Chester Hasbrouck</first-name> 
    <Descritpion>Hi</Descritpion> 
    <Descritpion>This is Chester </Descritpion> 
    <street>1234 Main Street</street> 
    <city>Sheboygan</city> 
    <state>WI</state> 
    <zip>48392</zip> 
    </address> 
    <address> 
    <first-name>Mary</first-name> 
    <Descritpion>Hi</Descritpion> 
    <Descritpion>This is Mary </Descritpion> 
    <Descritpion>Bye</Descritpion> 
    <street>283 First Avenue</street> 
    <city>Skunk Haven</city> 
    <state>MA</state> 
    <zip>02718</zip> 
    </address> 
</addressbook> 

... желаемый результат получается:

<?xml version="1.0" encoding="UTF-8"?><addressbook> 
    <address> 
    <first-name>Chester Hasbrouck</first-name> 
    <street>1234 Main Street</street> 
    <city>Sheboygan</city> 
    <state>WI</state> 
    <zip>48392</zip> 
    <Descritpion>Hi | This is Chester </Descritpion> 
    </address> 
    <address> 
    <first-name>Mary</first-name> 
    <street>283 First Avenue</street> 
    <city>Skunk Haven</city> 
    <state>MA</state> 
    <zip>02718</zip> 
    <Descritpion>Hi | This is Mary | Bye</Descritpion> 
    </address> 
</addressbook> 

Объяснение:

  • Шаблон №1: «Идентичный шаблон» копирует все как есть.

  • Шаблон # 2: этот шаблон копирует каждый элемент <address> как есть, создает новый <Descritpion> элемент, и инструктирует процессор XSLT, чтобы заполнить этот новый элемент с результатами любого шаблона, который соответствует Descritpion/text().

  • Шаблон №3: Этот шаблон обрабатывает результаты шаблона №2; в частности, он копирует текст из всех старых элементов <Descritpion> и, пока он не достигнет последнего, помещает | между результатами.

  • Шаблон №4: Этот шаблон удаляет оригинальные элементы <Descritpion> из исходного документа.