2017-08-07 77 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> 

预期输出:

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

对于每次发生:A:我需要创建一个<Detail>记录,然后为每个:B:将创建一个<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> 

演示:http://xsltransform.net/gVhD8Ro/1

+0

非常感谢! – Nathan

1

使用XSLT 3.0(如由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