如何使用 XSLT 转换和修改 (!) 嵌套标签?
How to transform and modify (!) nested tags with XSLT?
以这个XML为例...
<list>
<header>
something
</header>
<main>
<p>
(1) nothing <b>special</b> at all.
</p>
<p>
(1a) and <b>another</b> thing.
</p>
</main>
</list>
应转换为...
<list>
<header>
something
</header>
<aside>
<para nr="(1)">
nothing <u>special</u> at all.
</para>
<para nr="(1a)">
and <u>another</u> thing.
</para>
</aside>
</list>
This Whosebug answer was my starting point...
目前我没有真正的方法来解决这个问题。我不想引用我以前的失败...
我不记得回答过那个引用的问题,但我给出的答案是采取的方法。您只需要实施一些数字规则...
- 将
main
转换为aside
- 对于每个
p
标签,根据第一个子文本元素中括号中的值将 nr
属性添加到新创建的 para
标签中
- 将
p
元素下的 b
标签转换为 u
第二个有点棘手,但是可以用这个模板来实现,它利用一些字符串操作来提取括号中的数字
<xsl:template match="p">
<para nr="{substring-before(substring-after(text()[1], '('), ')')}">
<xsl:apply-templates select="@*|node()"/>
</para>
</xsl:template>
(还要注意使用Attribute Value Templates创建属性)
您还需要一个关联模板来从第一个文本节点中删除数字
<xsl:template match="p/text()[1]">
<xsl:value-of select="substring-after(., ')')" />
</xsl:template>
尽管将 b
转换为 u
更容易(假设只有 p
下的 b
个元素需要更改)。
<xsl:template match="p/b">
<u>
<xsl:apply-templates select="@*|node()"/>
</u>
</xsl:template>
将 main
更改为 aside
会有一个类似的模板
试试这个 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<!-- This is the Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="main">
<aside>
<xsl:apply-templates select="@*|node()"/>
</aside>
</xsl:template>
<xsl:template match="p">
<para nr="{substring-before(substring-after(text()[1], '('), ')')}">
<xsl:apply-templates select="@*|node()"/>
</para>
</xsl:template>
<xsl:template match="p/text()[1]">
<xsl:value-of select="substring-after(., ')')" />
</xsl:template>
<xsl:template match="p/b">
<u>
<xsl:apply-templates select="@*|node()"/>
</u>
</xsl:template>
</xsl:stylesheet>
以这个XML为例...
<list>
<header>
something
</header>
<main>
<p>
(1) nothing <b>special</b> at all.
</p>
<p>
(1a) and <b>another</b> thing.
</p>
</main>
</list>
应转换为...
<list>
<header>
something
</header>
<aside>
<para nr="(1)">
nothing <u>special</u> at all.
</para>
<para nr="(1a)">
and <u>another</u> thing.
</para>
</aside>
</list>
This Whosebug answer was my starting point...
目前我没有真正的方法来解决这个问题。我不想引用我以前的失败...
我不记得回答过那个引用的问题,但我给出的答案是采取的方法。您只需要实施一些数字规则...
- 将
main
转换为aside
- 对于每个
p
标签,根据第一个子文本元素中括号中的值将nr
属性添加到新创建的para
标签中 - 将
p
元素下的b
标签转换为u
第二个有点棘手,但是可以用这个模板来实现,它利用一些字符串操作来提取括号中的数字
<xsl:template match="p">
<para nr="{substring-before(substring-after(text()[1], '('), ')')}">
<xsl:apply-templates select="@*|node()"/>
</para>
</xsl:template>
(还要注意使用Attribute Value Templates创建属性)
您还需要一个关联模板来从第一个文本节点中删除数字
<xsl:template match="p/text()[1]">
<xsl:value-of select="substring-after(., ')')" />
</xsl:template>
尽管将 b
转换为 u
更容易(假设只有 p
下的 b
个元素需要更改)。
<xsl:template match="p/b">
<u>
<xsl:apply-templates select="@*|node()"/>
</u>
</xsl:template>
将 main
更改为 aside
试试这个 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<!-- This is the Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="main">
<aside>
<xsl:apply-templates select="@*|node()"/>
</aside>
</xsl:template>
<xsl:template match="p">
<para nr="{substring-before(substring-after(text()[1], '('), ')')}">
<xsl:apply-templates select="@*|node()"/>
</para>
</xsl:template>
<xsl:template match="p/text()[1]">
<xsl:value-of select="substring-after(., ')')" />
</xsl:template>
<xsl:template match="p/b">
<u>
<xsl:apply-templates select="@*|node()"/>
</u>
</xsl:template>
</xsl:stylesheet>