2017-08-07 5 views
0

J'ai presque le même problème pour celui-ci: Get value after each last colon. Dans mon cas, j'ai besoin de répéter pour chaque occurrence de: A: et: B :,: B: est un enfant de: A :. Dans mon code, j'utilise un modèle d'appel que je ne connais pas très bien. Mais, j'ai besoin d'explorer les autres fonctionnalités/éléments de xslt.Récupère la valeur après les deux points - clés

Voici mon fichier test échantillon:

<Record> 
:A:This is sample only 1 
:B:This is sample only 2 
:B:This is sample only 3 
:A:This is sample only 4 
:B:This is sample only 5 
</Record> 

Sortie prévue:

<Record> 
    <Detail> 
    <FieldA>This is sample only 1</FieldA> 
    <Trans> 
     <Group> 
     <FieldB>This is sample only 2</FieldB> 
     </Group> 
     <Group> 
     <FieldB>This is sample only 3</FieldB> 
     </Group> 
    </Trans> 
    </Detail> 
    <Detail> 
    <FieldA>This is sample only 4</FieldA> 
    <Trans> 
     <Group> 
     <FieldB>This is sample only 5</FieldB> 
     </Group> 
    </Trans> 
    </Detail> 
<Record> 

Pour chaque apparition: A :, je dois créer un dossier <Detail>, puis pour chaque: B: va créer un enregistrement <Group>. Et voici mon code XSLT,

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
<xsl:output method="xml" version="1.0" indent="yes"/> 
<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="Record"> 
    <xsl:call-template name="FormatXML"> 
     <xsl:with-param name="Input"> 
      <Record> 
      <xsl:for-each select="tokenize(.,':A:')"> 
       <xsl:analyze-string select="." regex=":([0-9A-Za-z]+):(.*)\n"> 
        <xsl:matching-substring> 
         <xsl:variable name="FieldA"> 
          <xsl:if test="regex-group(1) = 'A'"> 
           <FieldB> 
            <xsl:value-of select="regex-group(2)"/> 
           </FieldB> 
          </xsl:if> 
         </xsl:variable> 
         <xsl:for-each select="tokenize(.,':B:')"> 
         <xsl:variable name="FieldB"> 
          <xsl:if test="regex-group(1) = 'B'"> 
           <FieldB> 
            <xsl:value-of select="regex-group(2)"/> 
           </FieldB> 
          </xsl:if> 
         </xsl:variable> 
         <Group> 
          <FieldB> 
           <xsl:value-of select="$FieldB"/> 
          </FieldB> 
         </Group> 
         </xsl:for-each> 
         <Detail> 
          <FieldA> 
           <xsl:value-of select="$FieldA"/> 
          </FieldA> 
         </Detail> 
        </xsl:matching-substring> 
       </xsl:analyze-string>     
      </xsl:for-each> 
      </Record> 
     </xsl:with-param> 
    </xsl:call-template> 
</xsl:template> 
<xsl:template name="FormatXML"> 
    <xsl:param name="Input"/> 
    <xsl:apply-templates select="$Input"/>  
</xsl:template> 
<xsl:template match="/Record"> 
    <xsl:copy> 
     <xsl:apply-templates select="Detail"/> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="Detail"> 
    <xsl:copy> 
     <xsl:copy-of select="FieldA"/> 
     <Trans> 
      <xsl:apply-templates select="Group"/> 
     </Trans> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="Group"> 
    <xsl:copy> 
     <xsl:apply-templates select="FieldB"/> 
    </xsl:copy> 
</xsl:template> 

Mon code xslt ne fonctionne pas. Quelqu'un peut-il m'aider si ce que j'ai manqué dans mon code. Vos commentaires sont les bienvenus.

Merci!

Répondre

1

Je suggère une approche radicalement différente: d'abord convertir la chaîne en éléments individuels, de sorte que vous avez:

<FieldA>This is sample only 1</FieldA> 
<FieldB>This is sample only 2</FieldB> 
<FieldB>This is sample only 3</FieldB> 
<FieldA>This is sample only 4</FieldA> 
<FieldB>This is sample only 5</FieldB> 

dans une variable.

ensuite regrouper les éléments de la variable et les sortir de la façon dont vous voulez:

XSLT 2,0

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

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

<xsl:template match="Record"> 
    <!-- convert strings to elements --> 
    <xsl:variable name="temp" as="element()*"> 
     <xsl:analyze-string select="." regex="^:([AB]):(.*)$" flags="m"> 
      <xsl:matching-substring> 
       <xsl:element name="Field{regex-group(1)}"> 
        <xsl:value-of select="regex-group(2)" /> 
       </xsl:element> 
      </xsl:matching-substring> 
     </xsl:analyze-string> 
    </xsl:variable> 
    <!-- output --> 
    <xsl:copy> 
     <!-- group elements --> 
     <xsl:for-each-group select="$temp" group-starting-with="FieldA"> 
      <Detail> 
       <xsl:copy-of select="current-group()[1]" /> 
       <Trans> 
        <xsl:for-each select="current-group()[position() ge 2]"> 
         <Group> 
          <xsl:copy-of select="." /> 
         </Group> 
        </xsl:for-each> 
       </Trans> 
      </Detail> 
     </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

Démo: http://xsltransform.net/gVhD8Ro/1

+0

Merci beaucoup! – Nathan

1

Avec XSLT 3.0 (comme supporté par Saxon 9.8 toutes les éditions) ou Altova XMLSpy et Raptor vous pouvez directement regrouper les lignes:

<?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" 
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math" 
    expand-text="true" version="3.0"> 

    <xsl:output indent="yes"/> 

    <xsl:template match="Record"> 
     <xsl:copy> 
      <xsl:for-each-group select="tokenize(., '\r?\n')[normalize-space()]" 
       group-starting-with=".[starts-with(., ':A:')]"> 
       <Detail> 
        <FieldA>{replace(., ':A:', '')}</FieldA> 
        <Trans> 
         <xsl:apply-templates select="current-group()[position() gt 1]"/> 
        </Trans> 
       </Detail> 
      </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match=".[starts-with(., ':B:')]"> 
     <Group> 
      <FieldB>{replace(., ':B:', '')}</FieldB> 
     </Group> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Merci beaucoup! – Nathan