将 TEI p 转换为 lg
Transforming TEI p into lg
我有 TEI(文本编码倡议)文档,其中包含
<div>
<p>
some text, and maybe nodes <note>A note</note><lb />
and some more text<lb />
final line without lb
</p>
</div>
我想将其转换为:
<div>
<lg>
<l>some text, and maybe nodes <note>A note</note></l>
<l>and some more text</l>
<l>final line without lb</l>
</lg>
</div>
使用
将 p 转换为 lg 很简单
<xsl:template match="tei:div/tei:p">
<lg>
<xsl:apply-templates/>
</lg>
</xsl:template>
但其余的我不知道该怎么做。将一系列节点变成新父节点的子节点。
如果有 xslt 1.0 的解决方案那就太好了。
您可以在此处使用一种称为 Muenchian grouping 的技术。在这种情况下,您可以将 p
元素的子节点按其后 lb
元素的数量分组
<xsl:key name="p-nodes" match="tei:p/node()" use="concat(generate-id(..), '|', count(following-sibling::tei:lb))" />
要获得每个组中的第一个节点,它将代表每个 l
你想要输出,你会 select 他们像这样...
<xsl:for-each
select="node()[generate-id() = generate-id(key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[1])]">
并输出<l>
标签本身和组的内容,再次使用密钥...
<l><xsl:apply-templates select="key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[not(self::tei:lb)]" /></l>
试试这个 XSLT(显然更改 tei
前缀的名称空间以匹配 XML 中的真实名称)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:tei="tei">
<xsl:output method="xml" indent="yes" />
<xsl:key name="p-nodes" match="tei:p/node()" use="concat(generate-id(..), '|', count(following-sibling::tei:lb))" />
<xsl:template match="tei:div/tei:p">
<lg>
<xsl:variable name="parentId" select="generate-id()" />
<xsl:for-each select="node()[generate-id() = generate-id(key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[1])]">
<l><xsl:apply-templates select="key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[not(self::tei:lb)]" /></l>
</xsl:for-each>
</lg>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
查看实际效果
这是您可以查看的另一种方式。它使用 key 到 link 每个节点到其最近的前一个 lb
分隔符。这使您能够通过前导分隔符的唯一 id 获取每个组(第一个除外):
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:key name="following-nodes" match="node()[not(self::lb)]" use="generate-id(preceding-sibling::lb[1])" />
<xsl:template match="p[lb]">
<lg>
<l>
<xsl:apply-templates select="lb[1]/preceding-sibling::node()"/>
</l>
<xsl:for-each select="lb">
<l>
<xsl:apply-templates select="key('following-nodes', generate-id())"/>
</l>
</xsl:for-each>
</lg>
</xsl:template>
</xsl:stylesheet>
这个例子没有使用命名空间,因为你的问题没有定义它们。
我有 TEI(文本编码倡议)文档,其中包含
<div>
<p>
some text, and maybe nodes <note>A note</note><lb />
and some more text<lb />
final line without lb
</p>
</div>
我想将其转换为:
<div>
<lg>
<l>some text, and maybe nodes <note>A note</note></l>
<l>and some more text</l>
<l>final line without lb</l>
</lg>
</div>
使用
将 p 转换为 lg 很简单<xsl:template match="tei:div/tei:p">
<lg>
<xsl:apply-templates/>
</lg>
</xsl:template>
但其余的我不知道该怎么做。将一系列节点变成新父节点的子节点。
如果有 xslt 1.0 的解决方案那就太好了。
您可以在此处使用一种称为 Muenchian grouping 的技术。在这种情况下,您可以将 p
元素的子节点按其后 lb
元素的数量分组
<xsl:key name="p-nodes" match="tei:p/node()" use="concat(generate-id(..), '|', count(following-sibling::tei:lb))" />
要获得每个组中的第一个节点,它将代表每个 l
你想要输出,你会 select 他们像这样...
<xsl:for-each
select="node()[generate-id() = generate-id(key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[1])]">
并输出<l>
标签本身和组的内容,再次使用密钥...
<l><xsl:apply-templates select="key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[not(self::tei:lb)]" /></l>
试试这个 XSLT(显然更改 tei
前缀的名称空间以匹配 XML 中的真实名称)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:tei="tei">
<xsl:output method="xml" indent="yes" />
<xsl:key name="p-nodes" match="tei:p/node()" use="concat(generate-id(..), '|', count(following-sibling::tei:lb))" />
<xsl:template match="tei:div/tei:p">
<lg>
<xsl:variable name="parentId" select="generate-id()" />
<xsl:for-each select="node()[generate-id() = generate-id(key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[1])]">
<l><xsl:apply-templates select="key('p-nodes', concat($parentId, '|', count(following-sibling::tei:lb)))[not(self::tei:lb)]" /></l>
</xsl:for-each>
</lg>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
查看实际效果
这是您可以查看的另一种方式。它使用 key 到 link 每个节点到其最近的前一个 lb
分隔符。这使您能够通过前导分隔符的唯一 id 获取每个组(第一个除外):
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:key name="following-nodes" match="node()[not(self::lb)]" use="generate-id(preceding-sibling::lb[1])" />
<xsl:template match="p[lb]">
<lg>
<l>
<xsl:apply-templates select="lb[1]/preceding-sibling::node()"/>
</l>
<xsl:for-each select="lb">
<l>
<xsl:apply-templates select="key('following-nodes', generate-id())"/>
</l>
</xsl:for-each>
</lg>
</xsl:template>
</xsl:stylesheet>
这个例子没有使用命名空间,因为你的问题没有定义它们。