0

我有一个 XML 文档,其中的记录具有英语和西班牙语主题标签的单独字段。各个标签用分号分隔。

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

3 回答 3

1

XPath 3.0 中 fn:for-each-pair 的一个很好的用例:

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

在 Saxon-PE 9.5.1.1 中可用。

于 2013-07-31T20:25:14.460 回答
1

在 XPath 3.0 和 Saxon-PE 9.5.1.1 中使用 fn:for-each-pair,所需的输出由以下样式表生成:

<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>
于 2013-08-01T18:43:46.697 回答
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>

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

于 2013-07-31T17:16:47.403 回答