我有一个xml文档,如下所示:
<div>
<p>Hello my name is Bob <cb ed="#R" n="1/>and I live in a house</p>
<p>My name is Susan.</p>
<p>Where are you from?</p>
<p>I am from <cb ed="#R" n="2/>Chicago, Illinois</p>
<p>I also live in Chicago</p>
<p>But I wish I <cb ed="#R" n="3"/>lived in New York</p>
</div>
依旧......
我基本上想要转换它,所以标签包围了第一个和第二个之间的所有东西,依此类推......但我还想保留新创建的div中的现有段落。这意味着还要在文本节点周围创建一个
标记,该标记是该元素的后续兄弟。
我希望结果看起来像:
<div id="1">
<p>and I live in a house</p>
<p>My name is Susan.</p>
<p>Where are you from?</p>
<p>I am from</p>
</div>
<div id="2">
<p>Chicago, Illinois</p>
<p>I also live in Chicago</p>
<p>But I wish I</p>
</div>
<div id="3">
<p>lived in New York</p>
</div>
这证明相当困难。我想知道是否有人可以帮助我走上正确的轨道 - 或者指出一个类似转型的例子。
这是我到目前为止所拥有的:
<xsl:template match="tei:p">
<xsl:choose>
<xsl:when test="./tei:cb[@ed='#R']">
<xsl:variable name="number" select="./tei:cb[@ed='#R']/@n"/>
<div id="{$number}">
<span>test</span>
<xsl:for-each select="./tei:cb[@ed='#R']/following::p[preceding::tei:cb[@ed='#R']]">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
</div>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
到目前为止唯一的结果是:
<div id="1rb"><span>test</span></div>
<div id="1va"><span>test</span></div>
<div id="1vb"><span>test</span></div>
答案 0 :(得分:1)
以下适用于我。它使用计数技术来查找两个cb
元素之间的文本节点。
<xsl:template match="div">
<xsl:apply-templates select=".//cb"/>
</xsl:template>
<xsl:template match="cb">
<div id="{@n}">
<xsl:variable name="numTextNodes" select="count(following::text()) - count(following::cb/following::text())"/>
<xsl:for-each select="following::text()[position() <= $numTextNodes]">
<xsl:if test="normalize-space()">
<p>
<xsl:value-of select="normalize-space()"/>
</p>
</xsl:if>
</xsl:for-each>
</div>
</xsl:template>
答案 1 :(得分:1)
假设<cb>
总是出现在同一级别(<p>
之内),这或多或少类似"Create an hierarchical xml form an flat xml"或者看Kayessian method。
尝试这样的事情(仍然可以改进):
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[cb]" >
<!-- following siblings including next p[cb] -->
<xsl:variable name="fs" select="following-sibling::*[
generate-id( preceding-sibling::p[cb][1]
) = generate-id(current()) ]" />
<div id="{cb/@n}">
<xsl:apply-templates select="cb" mode="start"/>
<xsl:apply-templates select="$fs[position() != last()]" />
<xsl:apply-templates select="$fs[last()]" mode="stop"/>
</div>
</xsl:template>
<xsl:template match="p[cb]" mode="stop">
<p>
<xsl:copy-of select="cb/preceding-sibling::node()"/>
</p>
</xsl:template>
<xsl:template match="cb[parent::p]" mode="start">
<p>
<xsl:copy-of select="following-sibling::node()"/>
</p>
</xsl:template>
<xsl:template match="div[p/cb]">
<xsl:copy>
<xsl:apply-templates select="p[cb][1]" mode="stop"/>
<xsl:apply-templates select="p[cb]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
将生成以下输出:
<div>
<p>Hello my name is Bob </p>
<div id="1">
<p>and I live in a house</p>
<p>My name is Susan.</p>
<p>Where are you from?</p>
<p>I am from </p>
</div>
<div id="2">
<p>Chicago, Illinois</p>
<p>I also live in Chicago</p>
<p>But I wish I </p>
</div>
<div id="3">
<p>lived in New York</p>
</div>
</div>