2015-03-09 1 views
1

Я новичок в преобразовании XSL. Я преобразуя следующий XML в другой формат XML:XSL-трансформация - как искать связующий узел

<root> 

<header> 
    <section id="a1"> 
    <color>red</color> 
    </section> 

    <section id="a2"> 
    <color>blue</color> 
    </section> 

</header> 

<body> 
    This is the sample text <reference link="a1">with color red</reference> 
    and <reference link="a2">with color blue</reference> 
</body> 

</root> 

Раздел идентификатор (в заголовке) связан с опорным звеном (в теле). Я должен искать цвет «синий» в узле <color>. Если он доступен, мне нужно удалить родительский узел <section>. Наряду с этим, «id» этого раздела «a2». Соответствующая ссылка в теле должна быть удалена. Результат:

<root> 

<header> 
    <section id="a1"> 
    <color>red</color> 
    </section> 

</header> 

<body> 
    This is the sample text <reference link="a1">with color red</reference> 
    and with color blue 
</body> 

</root> 

Может кто-нибудь, пожалуйста, дать некоторые подсказки о том, как начать?

+0

Можете ли вы использовать XSLT 2.0 или вы ограничены 1.0? Вы хотите жестко закодировать «синий» в качестве цели или нужно передать его в качестве параметра? –

+0

Сервер имеет Java 1.5. Поддерживает ли он XSLT 2.0? Не могли бы вы рассказать, как проверить версию? Я хочу жестко записать «синий». – Mahesh

+0

@Mahesh: Я считаю, что JDK 1.5 поставляется с версией Xalan, которая реализует XSLT 1.0, но вы можете легко переключиться на Saxon и запустить XSLT 2.0. – kjhughes

ответ

3

Вы должны иметь возможность получить @id участка, который имеет blue, а затем разделите его на section и «развернуть» reference.

Вот 2 примера. Один в XSLT 1.0 и один в XSLT 2.0.

XSLT 1,0

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

    <xsl:param name="toStrip" select="'blue'"/> 
    <xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/> 

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

    <xsl:template match="header"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()[not(self::section[@id=$stripRef])]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="reference"> 
     <xsl:choose> 
      <xsl:when test="@link=$stripRef"> 
       <xsl:apply-templates/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:copy> 
        <xsl:apply-templates select="@*|node()"/> 
       </xsl:copy> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

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="*"/> 

    <xsl:param name="toStrip" select="'blue'"/> 
    <xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/> 

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

    <xsl:template match="section[@id=$stripRef]"/> 

    <xsl:template match="reference[@link=$stripRef]"> 
     <xsl:apply-templates/> 
    </xsl:template>  

</xsl:stylesheet> 

РЕДАКТИРОВАТЬ НА ОСНОВЕ КОММЕНТАРИЕВ

Вот один из способов, вы можете обрабатывать несколько идентификаторов. Поскольку параметр toStrip не может быть последовательностью, нам нужно добавить символ, чтобы разграничить значения. В этом примере я использовал |. Это так, что не соответствует действительности при сравнении чего-то вроде a1 с a10.

Кроме того, XSLT 1.0 вернет только первый @id в поле выбора . Чтобы получить все ID, я добавил xsl:for-each. Вы также можете сделать это с помощью xsl:apply-templates с помощью режима.

Вот обновленный XSLT:

XSLT 1,0

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

    <xsl:param name="toStrip" select="'|blue|orange|'"/> 
    <xsl:variable name="stripRef"> 
     <xsl:text>|</xsl:text> 
     <xsl:for-each select="//section[color[contains($toStrip,concat('|',.,'|'))]]/@id"> 
      <xsl:value-of select="concat(.,'|')"/> 
     </xsl:for-each> 
    </xsl:variable> 

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

    <xsl:template match="header"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()[not(self::section[contains($stripRef,concat('|',@id,'|'))])]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="reference"> 
     <xsl:message>contains(<xsl:value-of select="$stripRef"/>,<xsl:value-of select="concat('|',@link,'|')"/>)</xsl:message> 
     <xsl:choose> 
      <xsl:when test="contains($stripRef,concat('|',@link,'|'))"> 
       <xsl:apply-templates/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:copy> 
        <xsl:apply-templates select="@*|node()"/> 
       </xsl:copy> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

Чтобы сделать это же самое в XSLT 2.0, вам просто нужно будет изменить toStrip параметров последовательности:

<xsl:param name="toStrip" select="('blue','orange')"/> 
+0

Вы можете обнаружить, что версия «2.0» действительно работает в вашей существующей настройке Xalan - спецификация XSLT 1.0 запрещает использование ссылок на переменные в шаблонах совпадений, но я обнаружил, что Xalan действительно разрешает это, по крайней мере, в некоторых версиях , –

+0

@ Даниэль Хейли: Большое спасибо за помощь. У меня есть другой запрос. Есть ли способ получить несколько идентификаторов в StripRef?Например, если я хочу исключить синий и оранжевый. – Mahesh

+0

@Mahesh - Да, это возможно. Это очень легко в 2.0. Вы используете 2.0 или 1.0? –

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