我正在将XML文件转换为XSLT 3.0中的CSV文件,但仅处理某些节点。其中一个节点是一个由空格分隔的多个值的属性,我想将这些值中的每一个分解为目标CSV文件中的单独一行。
示例源XML文件:
<corpus>
<deposition>
<deposition-number n="dep1"/>
<text>
<seg n="seg1">Lorem ipsum dolor sit amet, <persName name="personA" ana="foo1 foo2">some foo person</persName>
adipiscing elit. Vivamu ultrices consequat facilisis.
Suspendisse a odio in lobortis. Aenean <persName name="personG" ana="foo2">some foo person</persName>
non dui scelerisque, rutrum est at, cursus sem.</seg>
<seg n="seg2">Ut pharetra <persName name="personF" ana="foo9">some foo person</persName>bibendum ipsum, portitor
velit pharetra quis. Aeneano purus. Praesent
aliquam viverra tellus.</seg>
</text>
</deposition>
<deposition>
<deposition-number n=""dep2"/>
<text>
<seg n="seg3">Curabitur pulvinar leo eget. Orci varius
natoque penatibus et magnis <persName name="personD" ana="foo2 foo3 foo8">some foo person</persName>montes,
nascetur ridiculus mus.</seg>
</text>
</deposition>
</corpus>
目前我可以在CSV中输出这个令人不满意的结果,其中@ana
位于最后一个字段中:
dep1~seg1~personA~foo1 foo2
dep1~seg1~personG~foo2
dep1~seg2~personF~foo9
dep1~seg3~personD~foo2 foo3 foo8
使用如下所示的XSL:
<xsl:template match="/">
<xsl:for-each select="persName">
<xsl:value-of select="ancestor::deposition-number/@n"/>
<xsl:text>~</xsl:text>
<xsl:value-of select="ancestor::seg/@n"/>
<xsl:text>~</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>~</xsl:text>
<xsl:value-of select="@ana"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
但我想输出这个,@ana
被解析为不同的行:
dep1~seg1~personA~foo1
dep1~seg1~personA~foo2
dep1~seg1~personG~foo2
dep1~seg2~personF~foo9
dep1~seg3~personD~foo2
dep1~seg3~personD~foo3
dep1~seg3~personD~foo8
我已经尝试过标记化,但如果它能够解决这个问题,我不知道该怎么做。我不知道如何解析@ana
并循环它。
提前致谢。
答案 0 :(得分:3)
请尝试使用此模板,该模板使用tokenize
拆分属性并为每个值输出一行
<xsl:template match="/">
<xsl:for-each select="//persName">
<xsl:variable name="pers" select="." />
<xsl:for-each select="tokenize(@ana, ' ')">
<xsl:value-of select="$pers/ancestor::deposition/deposition-number/@n"/>
<xsl:text>~</xsl:text>
<xsl:value-of select="$pers/ancestor::seg/@n"/>
<xsl:text>~</xsl:text>
<xsl:value-of select="$pers/@name"/>
<xsl:text>~</xsl:text>
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
(请注意,deposition-number
不是XML中persName
的祖先)
或者,为了简化它,试试这个......
<xsl:template match="/">
<xsl:for-each select="//persName">
<xsl:variable name="pers" select="." />
<xsl:for-each select="tokenize(@ana, ' ')">
<xsl:value-of select="($pers/ancestor::deposition/deposition-number/@n, $pers/ancestor::seg/@n, $pers/@name, .)" separator="~"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
答案 1 :(得分:2)
使用XSLT 3,您可以标记值并将它们推送到模板:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="3.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="//persName"/>
</xsl:template>
<xsl:template match="persName">
<xsl:apply-templates select="tokenize(@ana, '\s+')">
<xsl:with-param name="data" select="ancestor::deposition/deposition-number/@n, ancestor::seg/@n, @name"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match=".[. instance of xs:string]">
<xsl:param name="data"/>
<xsl:value-of select="$data, ." separator="~"/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>