2017-09-21 2 views
1

My XML.comment traiter les plages de numéros dans xslt2.0

<a> 
<range nr="1" no-range="1 2 3 4" oc="4"/> 
<range nr="2" no-range="41 42 43 44" oc="4"/> 
<range nr="3" no-range="43 44 45 46" oc="4"/> 
<range nr="4" no-range="50 51 52 53" oc="4"/> 
<range nr="5" no-range="53 54" oc="2"/> 
<range nr="6" no-range="60 61" oc="2"/> 
</a> 

je tentais cela, mais ne savez pas comment comparer deux tableaux et imprimer la différence:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> 
<xsl:template match="a"> 
    <xsl:variable name="bRannge"> 
     <xsl:for-each select="range"> 
      <xsl:variable name="aRange" select="tokenize(concat(@no-range, ' '), ' ')"/> 
      <xsl:value-of select="$aRange"/> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:variable name="cRange" select="tokenize(normalize-space($bRannge), ' ')"/> 
    <xsl:variable name="aSeq"> 
     <xsl:for-each select="1 to xs:integer(number($cRange[last()]))"> 
      <xsl:value-of select="position()"/> 
      <xsl:text> </xsl:text> 
     </xsl:for-each> 
    </xsl:variable>   
    <xsl:variable name="bSeq" select="tokenize(normalize-space($aSeq), ' ')"/> 
    [<xsl:value-of select="$cRange"/>] 
    [<xsl:value-of select="$bSeq"/>] 
    <!-- How to compare two arrays  --> 
</xsl:template> 

Comment puis-je obtenir le rapport suivant à l'aide xslt 2.0:

  1. Plages de numéros non utilisées 5-40, 47-49, 55-59
  2. 'nr 3' un chevauchement avec 'nr 2' Numéro de chevauchement = 43, 44
  3. 'NR 5' chevauche avec 'nr 4' Numéro de chevauchement = 53
+0

Honnêtement, je en doute la santé mentale d'utiliser XSLT pour cela. L'écriture d'une fonction d'extension permet-elle de passer l'élément 'a' à une option viable? – Flynn1179

+2

XSLT 2.0 est bien pour ça. Qu'avez-vous essayé? –

+0

@ C.M.Sperberg-McQueen S'il vous plaît voir question éditée avec mon xslt. J'ai deux tableaux, mais je ne sais pas comment imprimer la différence. –

Répondre

3

Vous pouvez créer chaque séquence que vous avez avec une seule expression puis de les comparer comme suit:

<xsl:template match="a"> 
    <xsl:variable name="seq1" as="xs:integer*" 
        select="for $s in range/@no-range/tokenize(., '\s+') 
          return xs:integer($s)"/> 
    <xsl:variable name="seq2" as="xs:integer*" 
        select="1 to $seq1[last()]"/> 

    [<xsl:value-of select="$seq1"/>] 
    [<xsl:value-of select="$seq2"/>] 
    [<xsl:value-of select="$seq2[not(. = $seq1)]"/>] 
</xsl:template> 

qui délivre en sortie la séquence de nombres entiers non dans vos no-range valeurs d'attribut:

[5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 2 2 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 47 48 49 55 56 57 58 59]

Quant à trouver les plages consécutives, une solution serait d'utiliser le regroupement comme suit:

<xsl:template match="a"> 
    <xsl:variable name="seq1" as="xs:integer*" 
        select="for $s in range/@no-range/tokenize(., '\s+') 
          return xs:integer($s)"/> 
    <xsl:variable name="seq2" as="xs:integer*" 
        select="1 to $seq1[last()]"/> 

    [<xsl:value-of select="$seq1"/>] 
    [<xsl:value-of select="$seq2"/>] 

    <xsl:variable name="seq3" as="xs:integer*" 
        select="$seq2[not(. = $seq1)]"/> 

    [<xsl:value-of select="$seq3"/>] 
    <xsl:for-each-group select="$seq3" group-adjacent=". - position()"> 
     [<xsl:value-of select="current-group()[1], current-group()[last()]" 
        separator=" - "/>]  
    </xsl:for-each-group> 

qui donne alors

[5 - 40]  

    [47 - 49]  

    [55 - 59] 
+0

merci! comment puis-je filtrer davantage la différence dans ce format - 5-40, 47-49, 55-59. –

+0

@DitaNewbieLa, voir la modification, une façon serait de grouper cette séquence. Comme alternative, vous pouvez traiter l'élément each range avec 'apply-templates' ou' for-each' et comparer la tokenisation de l'élément 'no-range' à celle du frère précédent ou suivant. –