XSLT устраняет указанные элементы в файле XML - PullRequest
0 голосов
/ 03 февраля 2012

У меня есть следующий XML-файл:

<guests>  
   <guest roomnumber="111" email="john.perry@abc.com"/>  
   <guest roomnumber="112" email="JohnMarconi@lema.fr"/>
   <guest roomnumber="114" email="John_kim@kema.nl"/>
   <guest roomnumber="127" email="jim.taylor@sat.com"/>
   <guest roomnumber="133" email="Jane.Doe@abc.com"/>  
   <guest roomnumber="135" email="janesullivan@ati.org"/>
   <guest roomnumber="136" email="Albert.Jones@lec.org"/>   
</guests> 

и хотел бы удалить элементы с @email, начиная с 'john' или 'jane', выполняя поиск имени без учета регистра.

Полученный XML-файл должен выглядеть примерно так:

<guests>  
   <guest roomnumber="127" email="jim.taylor@sat.com"/>
   <guest roomnumber="136" email="Albert.Jones@lec.org"/>   
</guests>

В преобразовании я хотел бы использовать параметр «Имя», например

   <xsl:param name="Name"> 
        <x>john</x> 
        <x>jane</x> 
    </xsl:param> 

или

 <xsl:param name="Name" select="'john,jane'" />

Как такое преобразование может быть реализовано с использованием XSLT 1.0? Увы, в моем случае XSLT 2.0 и функция document () не поддерживаются.

TIA, Лев

Ответы [ 2 ]

2 голосов
/ 03 февраля 2012

Предполагая, что вы передаете параметр $name в качестве фактического XML-документа (т. Е. Вы не определите его в документе XSLT, потому что это приведет к фрагменту результирующего дерева , который нелегко использовать без функции расширения):

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
  <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'" />

  <xsl:template match="*|@*">
    <xsl:if test="
      not(self::guest)
      or
      not($Name/x[starts-with(translate(current()/@email, $upper, $lower), .)])
    ">
      <xsl:copy>
       <xsl:apply-templates select="*|@*" />
      </xsl:copy>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

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


РЕДАКТИРОВАТЬ: Вот версия того же самого, которая использует встроенное определение имен и node-set():

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common" 
  exclude-result-prefixes="exsl"
>
  <xsl:output indent="yes" />

  <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
  <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'" />

  <xsl:param name="Name"> 
    <x>john</x> 
    <x>jane</x> 
  </xsl:param>

  <xsl:variable name="Excluded" select="exsl:node-set($Name)/x" />

  <xsl:template match="*|@*">
    <xsl:if test="
      not(self::guest)
      or
      not($Excluded[starts-with(translate(current()/@email, $upper, $lower), .)])
    ">
      <xsl:copy>
        <xsl:apply-templates select="*|@*" />
      </xsl:copy>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
1 голос
/ 03 февраля 2012

вы можете попробовать что-то в этом роде:

РЕДАКТИРОВАТЬ
Как указал Томалак, вам нужно преобразовать RTF (фрагмент дерева результатов) с нестандартнымxxx:node-set() функция!

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:msxsl="urn:schemas-microsoft-com:xslt"
     xmlns:ext="http://exslt.org/common"
     exclude-result-prefixes="ext msxsl">

    <xsl:variable name="lower">abcdefghijklmnopqrstuvwxyz</xsl:variable>
    <xsl:variable name="upper">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>

    <xsl:template match="/guests">
        <guests>
            <xsl:call-template name="foo">
                <xsl:with-param name="guests" select="guest"/>
                <xsl:with-param name="terms">
                    <x>John</x>
                    <x>jane</x>
                </xsl:with-param>
            </xsl:call-template>
        </guests>
    </xsl:template>

    <xsl:template name="foo">
        <xsl:param name="guests"/>
        <xsl:param name="terms"/>

        <xsl:for-each select="$guests">
            <xsl:call-template name="bar">
                <xsl:with-param name="guest" select="."/>
                <!-- HERE ARE THE EDITED LINES -->
                <xsl:with-param name="prefix" select="ext:node-set($terms)/*"/>
                <xsl:with-param name="runs" select="count(ext:node-set($terms)/*)"/>
                <!-- HERE ARE THE EDITED LINES -->
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="bar">
        <xsl:param name="runs" select="0"/>
        <xsl:param name="guest"/>
        <xsl:param name="prefix"/>

        <xsl:if test="not(starts-with(translate($guest/@email, $upper, $lower), translate($prefix, $upper, $lower)))">
            <xsl:choose>
                <xsl:when test="$runs = 1">
                    <xsl:copy-of select="$guest"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="bar">
                       <xsl:with-param name="guest" select="$guest"/>
                       <xsl:with-param name="prefix" select="$prefix[not(position()=1)]"/>
                       <xsl:with-param name="runs" select="$runs - 1"/>
                   </xsl:call-template>               
                </xsl:otherwise>
            </xsl:choose>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...