我有一个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> </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> </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
,但我还没有将它包含在样式表中。
添加了这些信息后,所需的输出将如下所示:
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 :(得分:1)
XPath 3.0中fn:for-each-pair的一个很好的用例:
for-each-pair(
tokenize($materia, '; '),
tokenize($subject, '; '),
function($x, $y) { $x || '_' || $y || '
' })
可在Saxon-PE 9.5.1.1中使用。
答案 1 :(得分: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 || '
' })">
<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> </xsl:text>
</xsl:for-each-group>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:template>
</stylesheet>
答案 2 :(得分: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=" "/>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
这样就够了吗?我不确定您希望代码以何种方式呈现动态,我假设您知道您感兴趣的name
元素的field
属性(即materia
,subject
)。