for my research project, I have this document in XML/TEI
在我的研究项目中,我有这个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>
I need to extract for each Tag contained in span/@ana : the date and the string length of the following node seg. With the condition that if we incounter the date attribute @from or @to, I just need the value of the @from. What I need would look like that :
我需要提取span/@ana中包含的每个标记:日期和以下节点seg的字符串长度。如果我们插入date属性@from或@to,我只需要@from的值。我需要的是:
Tag957;1980-01-01;88
Tag874;1980-01-01;88
Tag1657;1980-01-03;11
I tried this, but I don't know how to express that for-each is applyed to one attribute's value at a time
我尝试过这种方法,但是我不知道如何表达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>
3 个解决方案
#1
2
Using XSLT 2.0 you can use tokenize
to identify the different values in the attribute value, then you can rewrite your code as
使用XSLT 2.0,可以使用标记来标识属性值中的不同值,然后可以将代码重写为
<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>
Online at http://xsltransform.net/jz1PuPL.
在http://xsltransform.net/jz1PuPL在线。
#2
3
You made only a single loop for span
elements. It's not enough.
您仅为span元素创建了一个循环。这是不够的。
Actually, for each such span
you have to:
实际上,对于每一个这样的跨度,你必须:
- Read the
ana
attribute. - 阅读安娜属性。
- Tokienize it with a space (if you can, use XSLT 2.0, it has this function).
- 使用一个空格(如果可以的话,使用XSLT 2.0,它有这个函数)。
For each resulting token (not for the whole value of @ana
) you have to perform the inner for-each
loop:
对于每个结果令牌(不是@ana的整个值),您必须执行内部For -each循环:
- Find only the first following
seg
sibling and its childdate
element:select="following-sibling::tei:seg[1]/tei:date"
(note that I added [1]). - 只找到下面的第一个seg sibling及其子日期元素:select=“follow -sibling:::tei:seg[1]/tei:date”(注意我添加了[1])。
- Check whether it contains required attributes (
from
,to
orwhen
). - 检查它是否包含必需的属性(从、到或何时)。
If it does, then:
如果是这样,那么:
- Print the current token extracted from the current
ana
attribute. - 打印从当前的ana属性中提取的当前标记。
- Print the requred dates according to your need (from the current
date
element). - 根据需要打印请求日期(来自当前日期元素)。
- Print the rest of things to be printed.
- 打印其余要打印的东西。
It is only a sketch, I omitted such details as keeping the current values from both loops in respective variables.
这只是一个草图,我省略了一些细节,比如在各自的变量中保存两个循环的当前值。
I hope it will help you to reach the final result.
我希望它能帮助你达到最终的结果。
#3
1
XSLT-1.0
xslt 1.0
I create a recursive template to tokenize values inside ana
attribute, and call it for each span. I had to add a space on line 8 for the template to work: <xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/>
我创建一个递归模板,以在ana属性中标记值,并为每个span调用它。我必须在第8行上添加一个空格,以便模板能够工作:
<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>
Output:
输出:
Tag957;1980-01-01;105
Tag874;1980-01-01;105
Tag1657;1980-01-03;19
Online link: http://xsltransform.net/gWEamLJ/2
网络链接:http://xsltransform.net/gWEamLJ/2
#1
2
Using XSLT 2.0 you can use tokenize
to identify the different values in the attribute value, then you can rewrite your code as
使用XSLT 2.0,可以使用标记来标识属性值中的不同值,然后可以将代码重写为
<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>
Online at http://xsltransform.net/jz1PuPL.
在http://xsltransform.net/jz1PuPL在线。
#2
3
You made only a single loop for span
elements. It's not enough.
您仅为span元素创建了一个循环。这是不够的。
Actually, for each such span
you have to:
实际上,对于每一个这样的跨度,你必须:
- Read the
ana
attribute. - 阅读安娜属性。
- Tokienize it with a space (if you can, use XSLT 2.0, it has this function).
- 使用一个空格(如果可以的话,使用XSLT 2.0,它有这个函数)。
For each resulting token (not for the whole value of @ana
) you have to perform the inner for-each
loop:
对于每个结果令牌(不是@ana的整个值),您必须执行内部For -each循环:
- Find only the first following
seg
sibling and its childdate
element:select="following-sibling::tei:seg[1]/tei:date"
(note that I added [1]). - 只找到下面的第一个seg sibling及其子日期元素:select=“follow -sibling:::tei:seg[1]/tei:date”(注意我添加了[1])。
- Check whether it contains required attributes (
from
,to
orwhen
). - 检查它是否包含必需的属性(从、到或何时)。
If it does, then:
如果是这样,那么:
- Print the current token extracted from the current
ana
attribute. - 打印从当前的ana属性中提取的当前标记。
- Print the requred dates according to your need (from the current
date
element). - 根据需要打印请求日期(来自当前日期元素)。
- Print the rest of things to be printed.
- 打印其余要打印的东西。
It is only a sketch, I omitted such details as keeping the current values from both loops in respective variables.
这只是一个草图,我省略了一些细节,比如在各自的变量中保存两个循环的当前值。
I hope it will help you to reach the final result.
我希望它能帮助你达到最终的结果。
#3
1
XSLT-1.0
xslt 1.0
I create a recursive template to tokenize values inside ana
attribute, and call it for each span. I had to add a space on line 8 for the template to work: <xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/>
我创建一个递归模板,以在ana属性中标记值,并为每个span调用它。我必须在第8行上添加一个空格,以便模板能够工作:
<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>
Output:
输出:
Tag957;1980-01-01;105
Tag874;1980-01-01;105
Tag1657;1980-01-03;19
Online link: http://xsltransform.net/gWEamLJ/2
网络链接:http://xsltransform.net/gWEamLJ/2