XSL for-each on space-separated 属性值
XSL for-each on space-separated attribute values
对于我的研究项目,我在 XML/TEI
中有此文档
<TEI xmlns="http://www.tei-c.org/ns/1.0" >
<body>
<div>
<p>
<span target="#" type="passage" ana="Tag957 Tag874">
<span target="#" ana=""/>
</span>
<seg><date when="1980-01-01" type="date_seg"/>blabla blabla
blabla blablablabla blablablabla blablablabla blablablabla bl
</seg>
<span target="#" type="passage" ana="Tag1657 ">
<span target="#" ana=""/>
</span>
<seg><date from="1980-01-03" to="1980-01-05" type="date_seg"/>blabla
</seg>
</p>
</div>
</body>
</TEI>
我需要为 span/@ana 中包含的每个标签提取:以下节点段的日期和字符串长度。条件是如果我们遇到日期属性@from 或@to,我只需要@from 的值。
我需要的是这样的:
Tag957;1980-01-01;88
Tag874;1980-01-01;88
Tag1657;1980-01-03;11
我试过了,但我不知道如何表达 for-each 一次应用于一个属性的值
<xsl:template match="tei:p">
<xsl:for-each select="tei:span">
<xsl:value-of select="./@ana"/>
<xsl:text>;</xsl:text>
<xsl:if test="following-sibling::tei:seg/tei:date/@from or following-sibling::tei:seg/tei:date/@to">
<xsl:value-of select="following-sibling::tei:seg/tei:date/@from"/>
</xsl:if>
<xsl:if test="following-sibling::tei:seg/tei:date/@when">
<xsl:value-of select="following-sibling::tei:seg/tei:date/@when"/>
</xsl:if>
<xsl:text>;</xsl:text>
<xsl:value-of select="string-length(following-sibling::tei:seg)"/>
<xsl:text>;</xsl:text>
<xsl:value-of select="$newLine"/>
</xsl:for-each>
</xsl:template>
您只为 span
个元素制作了一个 单循环 。还不够。
实际上,对于每个这样的 span
你必须:
- 读取
ana
属性。
- 用space对其进行Tokienize化(如果可以的话,使用XSLT 2.0,它有这个功能)。
对于每个生成的标记(不是 @ana
的整个值),您必须执行内部 for-each
循环:
- 仅查找 第一个 跟随
seg
兄弟及其子 date
元素:
select="following-sibling::tei:seg[1]/tei:date"
(注意我加了[1])。
- 检查它是否包含必需的属性(
from
、to
或 when
)。
如果是,则:
- 打印从当前
ana
属性中提取的当前标记。
- 根据需要打印所需日期(从当前
date
元素)。
- 打印其余要打印的内容。
这只是一个草图,我省略了将两个循环的当前值保存在各自变量中的细节。
希望对您的最终结果有所帮助。
使用 XSLT 2.0,您可以使用 tokenize
来识别属性值中的不同值,然后您可以将代码重写为
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xpath-default-namespace="http://www.tei-c.org/ns/1.0">
<xsl:template match="p">
<xsl:for-each select="span">
<xsl:variable name="span" select="."/>
<xsl:for-each select="tokenize(@ana, '\s+')[normalize-space()]">
<xsl:value-of select="."/>
<xsl:text>;</xsl:text>
<xsl:if test="$span/following-sibling::seg[1]/date/@from or $span/following-sibling::seg[1]/date/@to">
<xsl:value-of select="$span/following-sibling::seg[1]/date/@from"/>
</xsl:if>
<xsl:if test="$span/following-sibling::seg/date/@when">
<xsl:value-of select="$span/following-sibling::seg/date/@when"/>
</xsl:if>
<xsl:text>;</xsl:text>
<xsl:value-of select="string-length($span/following-sibling::seg[1])"/>
<xsl:text>;</xsl:text>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:transform>
XSLT-1.0
我创建了一个递归模板来标记 ana
属性中的值,并为每个跨度调用它。我必须在第 8 行添加一个 space 才能使模板工作:
<xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0">
<xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="tei:p">
<xsl:for-each select="tei:span">
<xsl:call-template name="recurse_ana">
<xsl:with-param name="ana_val" select="substring-before(./@ana,' ')"/>
<xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/>
<xsl:with-param name="seg" select="following-sibling::tei:seg[1]"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="recurse_ana">
<xsl:param name="ana_val"/>
<xsl:param name="remaining-ana-val"/>
<xsl:param name="seg"/>
<xsl:if test="string-length($ana_val) > 0"><xsl:value-of select="$ana_val"/>
<xsl:value-of select="';'"/>
<xsl:value-of select="$seg/tei:date/(@when|@from)"/>
<xsl:value-of select="';'"/>
<xsl:value-of select="string-length($seg)"/>
<xsl:value-of select="'
'"/>
<xsl:call-template name="recurse_ana">
<xsl:with-param name="ana_val" select="substring-before($remaining-ana-val,' ')"/>
<xsl:with-param name="remaining-ana-val" select="substring-after($remaining-ana-val,' ')"/>
<xsl:with-param name="seg" select="$seg"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
输出:
Tag957;1980-01-01;105
Tag874;1980-01-01;105
Tag1657;1980-01-03;19
对于我的研究项目,我在 XML/TEI
中有此文档<TEI xmlns="http://www.tei-c.org/ns/1.0" >
<body>
<div>
<p>
<span target="#" type="passage" ana="Tag957 Tag874">
<span target="#" ana=""/>
</span>
<seg><date when="1980-01-01" type="date_seg"/>blabla blabla
blabla blablablabla blablablabla blablablabla blablablabla bl
</seg>
<span target="#" type="passage" ana="Tag1657 ">
<span target="#" ana=""/>
</span>
<seg><date from="1980-01-03" to="1980-01-05" type="date_seg"/>blabla
</seg>
</p>
</div>
</body>
</TEI>
我需要为 span/@ana 中包含的每个标签提取:以下节点段的日期和字符串长度。条件是如果我们遇到日期属性@from 或@to,我只需要@from 的值。 我需要的是这样的:
Tag957;1980-01-01;88
Tag874;1980-01-01;88
Tag1657;1980-01-03;11
我试过了,但我不知道如何表达 for-each 一次应用于一个属性的值
<xsl:template match="tei:p">
<xsl:for-each select="tei:span">
<xsl:value-of select="./@ana"/>
<xsl:text>;</xsl:text>
<xsl:if test="following-sibling::tei:seg/tei:date/@from or following-sibling::tei:seg/tei:date/@to">
<xsl:value-of select="following-sibling::tei:seg/tei:date/@from"/>
</xsl:if>
<xsl:if test="following-sibling::tei:seg/tei:date/@when">
<xsl:value-of select="following-sibling::tei:seg/tei:date/@when"/>
</xsl:if>
<xsl:text>;</xsl:text>
<xsl:value-of select="string-length(following-sibling::tei:seg)"/>
<xsl:text>;</xsl:text>
<xsl:value-of select="$newLine"/>
</xsl:for-each>
</xsl:template>
您只为 span
个元素制作了一个 单循环 。还不够。
实际上,对于每个这样的 span
你必须:
- 读取
ana
属性。 - 用space对其进行Tokienize化(如果可以的话,使用XSLT 2.0,它有这个功能)。
对于每个生成的标记(不是 @ana
的整个值),您必须执行内部 for-each
循环:
- 仅查找 第一个 跟随
seg
兄弟及其子date
元素:select="following-sibling::tei:seg[1]/tei:date"
(注意我加了[1])。 - 检查它是否包含必需的属性(
from
、to
或when
)。
如果是,则:
- 打印从当前
ana
属性中提取的当前标记。 - 根据需要打印所需日期(从当前
date
元素)。 - 打印其余要打印的内容。
这只是一个草图,我省略了将两个循环的当前值保存在各自变量中的细节。
希望对您的最终结果有所帮助。
使用 XSLT 2.0,您可以使用 tokenize
来识别属性值中的不同值,然后您可以将代码重写为
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xpath-default-namespace="http://www.tei-c.org/ns/1.0">
<xsl:template match="p">
<xsl:for-each select="span">
<xsl:variable name="span" select="."/>
<xsl:for-each select="tokenize(@ana, '\s+')[normalize-space()]">
<xsl:value-of select="."/>
<xsl:text>;</xsl:text>
<xsl:if test="$span/following-sibling::seg[1]/date/@from or $span/following-sibling::seg[1]/date/@to">
<xsl:value-of select="$span/following-sibling::seg[1]/date/@from"/>
</xsl:if>
<xsl:if test="$span/following-sibling::seg/date/@when">
<xsl:value-of select="$span/following-sibling::seg/date/@when"/>
</xsl:if>
<xsl:text>;</xsl:text>
<xsl:value-of select="string-length($span/following-sibling::seg[1])"/>
<xsl:text>;</xsl:text>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:transform>
XSLT-1.0
我创建了一个递归模板来标记 ana
属性中的值,并为每个跨度调用它。我必须在第 8 行添加一个 space 才能使模板工作:
<xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0">
<xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="tei:p">
<xsl:for-each select="tei:span">
<xsl:call-template name="recurse_ana">
<xsl:with-param name="ana_val" select="substring-before(./@ana,' ')"/>
<xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/>
<xsl:with-param name="seg" select="following-sibling::tei:seg[1]"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="recurse_ana">
<xsl:param name="ana_val"/>
<xsl:param name="remaining-ana-val"/>
<xsl:param name="seg"/>
<xsl:if test="string-length($ana_val) > 0"><xsl:value-of select="$ana_val"/>
<xsl:value-of select="';'"/>
<xsl:value-of select="$seg/tei:date/(@when|@from)"/>
<xsl:value-of select="';'"/>
<xsl:value-of select="string-length($seg)"/>
<xsl:value-of select="'
'"/>
<xsl:call-template name="recurse_ana">
<xsl:with-param name="ana_val" select="substring-before($remaining-ana-val,' ')"/>
<xsl:with-param name="remaining-ana-val" select="substring-after($remaining-ana-val,' ')"/>
<xsl:with-param name="seg" select="$seg"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
输出:
Tag957;1980-01-01;105
Tag874;1980-01-01;105
Tag1657;1980-01-03;19