2013-07-31 38 views
0

我有一个XML文档,其中包含具有用于英语和西班牙语的主题标签的单独字段的记录。各个标签以分号分隔。使用XSLT根据位置对齐字段

<collections> 
    <collection name="anyCollection"> 
    <record> 
     <field name="materia">comida; bebida; fiesta</field> 
     <field name="subject">food; drink; party</field> 
     <field name="recordid">abc0001</field> 
    </record> 
    <record> 
     <field name="materia">comida; bebida; fiesta</field> 
     <field name="subject">food; drink; party</field> 
     <field name="recordid">abc0002</field> 
    </record> 
    <record> 
     <field name="materia">comida; bebida; fiesta</field> 
     <field name="subject">food; drink; party</field> 
     <field name="recordid">abc0003</field> 
    </record> 
    <record> 
     <field name="materia">fiesta; sombreros; música; baile; agua; cerveza; sopa</field> 
     <field name="subject">party; hats; music; dance; water; beer; soup</field> 
     <field name="recordid">abc0004</field> 
    </record> 
    <record> 
     <field name="materia">comida; bebida; fiesta; sombreros; música</field> 
     <field name="subject">food; drink; party; hats; music</field> 
     <field name="recordid">abc0005</field> 
    </record> 
    <record> 
     <field name="materia">comida; bebida; cerveza; agua</field> 
     <field name="subject">food; drink; beer; water</field>    
     <field name="recordid">abc0006</field> 
    </record>   
    <record> 
     <field name="materia">fiesta; sombreros; música; baile; agua; cerveza</field> 
     <field name="subject">party; hats; music; dance; water; beer</field> 
     <field name="recordid">abc0007</field> 
    </record>  
    </collection> 
</collections> 

我希望能够为输出与分组和位置对齐,这样我可以肯定,他们是彼此的镜像的两个字段的内容的文本文件。这是我目前的样式表。它产生我想要的基本输出,但不会动态执行。基本上,我希望能够按位置迭代每个字段的内容。我猜我需要某种递归模板或函数,但我很难搞清楚。

<?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:variable name="field"> 
    <xsl:for-each 
     select="collections/collection[@name='anyCollection']/record"> 
     <record> 
     <xsl:for-each select="field"> 
      <field> 
      <xsl:for-each select="tokenize(.[@name='materia'],';')"> 
       <materia> 
       <xsl:value-of select="."/> 
       </materia> 
      </xsl:for-each> 
      <xsl:for-each select="tokenize(.[@name='subject'],';')"> 
       <subject> 
       <xsl:value-of select="."/> 
       </subject> 
      </xsl:for-each> 
      </field> 
     </xsl:for-each> 
     </record> 
    </xsl:for-each> 
    </xsl:variable> 

    <xsl:variable name="align">   
    <xsl:for-each select="$field/record/field">   
     <languagePair1>     
     <xsl:for-each select="materia[1]">      
      <xsl:value-of select="."/> 
      <xsl:text>_</xsl:text>  
     </xsl:for-each> 
     <xsl:for-each select="subject[1]">      
      <xsl:value-of select="."/> 
      <xsl:text>&#10;</xsl:text>  
     </xsl:for-each> 
     </languagePair1> 
     <languagePair2> 
     <xsl:for-each select="materia[2]">      
      <xsl:value-of select="."/> 
      <xsl:text>_</xsl:text>  
     </xsl:for-each>            
     <xsl:for-each select="subject[2]">      
      <xsl:value-of select="."/> 
      <xsl:text>&#10;</xsl:text>  
     </xsl:for-each>        
     </languagePair2> 
    </xsl:for-each> 
    </xsl:variable> 

    <xsl:template match="/">    
    <xsl:for-each-group select="$align/languagePair1" group-by=".">   
     <xsl:value-of select="current-grouping-key()"/>   
    </xsl:for-each-group> 
    <xsl:for-each-group select="$align/languagePair2" group-by=".">   
     <xsl:value-of select="current-grouping-key()"/>    
    </xsl:for-each-group> 
    </xsl:template> 

</xsl:stylesheet> 

下面是基本的输出我想:

comida_food 

bebida_drink 

fiesta_party 

sombreros_hats 

música_music 

我还需要输出与每个标签相关的recordid S,但我一直没能在样式表中包括这个呢。

有了这些信息添加,所需的输出应该是这样的:

comida_food 
abc0001 
abc0002 
abc0003 
abc0005 
abc0006 

bebida_drink 
abc0001 
abc0002 
abc0003 
abc0005 
abc0006 

fiesta_party 
abc0001 
abc0002 
abc0003 
abc0004 
abc0005 
abc0007 

sombreros_hats 
abc0004 
abc0005 
abc0007 

música_music 
abc0004 
abc0005 
abc0007 
+0

更新XML输入以更好地反映的结构我的数据集。 – tat

+0

更新了输出以反映XML输入。 – tat

回答

1

一个很好的使用案例FN:的for-each-对在XPath中3.0:

for-each-pair(
    tokenize($materia, '; '), 
    tokenize($subject, '; '), 
    function($x, $y) { $x || '_' || $y || '&#xa;' }) 

可用在撒克逊-PE 9.5.1.1。

+0

谢谢。我期待着尝试一下! – tat

0

我可以得到你想要用下面的代码的输出:

<xsl:stylesheet version="2.0" exclude-result-prefixes="xs" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 


<xsl:output method="text"/> 

<xsl:template match="/"> 
    <xsl:for-each-group select="collections/collection[@name = 'anyCollection']/record" group-by="tokenize(field[@name = 'materia'], '; ')"> 
    <xsl:variable name="pos" select="position()"/> 
    <xsl:variable name="subjects" select="tokenize(field[@name = 'subject'], '; ')"/> 
    <xsl:value-of select="concat(current-grouping-key(), '_', $subjects[$pos]), current-group()/field[@name = 'recordid']" separator="&#10;"/> 
    <xsl:text>&#10;&#10;</xsl:text> 
    </xsl:for-each-group> 
</xsl:template> 

</xsl:stylesheet> 

这是否足够?我不确定您希望代码是以何种方式呈现动态,我假设您知道您感兴趣的field元素的name属性(即materia,subject)。

+0

谢谢。但是,这个解决方案似乎只适用于该系列的第一个记录。 '$ pos'变量中的'position()'计数并不对应于标记化节点的位置,而是对应于记录序列(即对每个新记录不重置计数)。 – tat

+0

我想我需要更新我的输入XML以更好地反映我正在使用的数据。 – tat

1

使用FN:的for-each-对在XPath中3.0撒克逊-PE 9.5.1.1,由下面的样式表产生所需的输出:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="3.0"> 

    <xsl:output method="text"/> 
    <xsl:template match="/"> 
    <xsl:for-each-group select="collections/collection[@name = 'anyCollection']/record" 
     group-by="for-each-pair(
     tokenize(field[@name = 'materia'], '; '), 
     tokenize(field[@name = 'subject'], '; '), 
     function($x, $y) { $x || '_' || $y || '&#xa;' })"> 

     <xsl:value-of select="current-grouping-key()"/> 

     <xsl:for-each-group select="current-group()" group-by="field[@name='recordid']"> 
     <xsl:sort select="substring(translate(current-grouping-key(),'ÁÉÍÓÚÜáéíóúü','AEIOUUaeiouu'),4)" data-type="number"/>     
     <xsl:value-of select="current-grouping-key()"/> 
     <xsl:text>&#10;</xsl:text>  
     </xsl:for-each-group> 

     <xsl:text>&#10;</xsl:text>      
    </xsl:for-each-group> 
    </xsl:template> 
</stylesheet>