2017-08-07 4 views
0

私はこの問題とほぼ同じ問題を持っています:Get value after each last colon。私の場合は、A:と:B:、B:はA:の子です。私のコードでは、コールテンプレートを使用していますが、これはあまりよく知られていません。しかし、私はxsltの他の機能/要素を探求する必要があります。コロンキーの後の値を取得

<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> 

予想される出力:B:私はその後、それぞれの<Detail>レコードを作成する必要があり:,:という語句の

<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> 

ここ

は私のサンプルテストファイルです。 <Group>レコードが作成されます。そして、ここに私の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> 

である私のXSLTコードが機能していません。私のコードで見逃したことがあれば誰でも助けてくれますか? ご意見をいただければ幸いです。

ありがとうございます!

答えて

1

私は根本的に異なるアプローチを示唆している:変数で

<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> 

を:あなたが持っているように、最初、個々の要素に文字列を変換します。

そして、グループ変数と出力それらの要素あなたがそれら望む方法:

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> 

デモ:XSLT 3.0でhttp://xsltransform.net/gVhD8Ro/1

+0

ありがとうございました! – Nathan

1

(などSaxon 9.8のすべてのエディションでサポートされています)またはAltova XMLSpyとRaptorを使用すると、行を直接グループ化することができます。

<?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

ありがとうございました! – Nathan

関連する問題