我正在尝试处理XML文件,我知道某些具有特定属性的元素应该是新元素的子元素。那些不匹配的元素的其他兄弟姐妹应该保持不变。一个例子会更好。
我要匹配的代币具有属性id =' t_15'和id =' t_16'。
这是输入XML:
<text>
<div id="d_1">
<p id="p_1">
<s id="s_1">
<token id="t_13" lemma="colleague" pos="NN">Colleagues</token>
<token id="t_14" lemma="," pos=",">,</token>
<token id="t_15" lemma="we" pos="PP">we</token>
<token id="t_16" lemma="now" pos="RB">now</token>
<token id="t_17" lemma="come" pos="VVP">come</token>
<token id="t_18" lemma="to" pos="TO">to</token>
<token id="t_19" lemma="catch-the-eye" pos="NN">catch-the-eye</token>
<token id="t_20" lemma="." pos="SENT">.</token>
</s>
<s id="s_2">
<token id="t_21" lemma="these" pos="DT">These</token>
<token id="t_22" lemma="be" pos="VBP">are</token>
<token id="t_23" lemma="the" pos="DT">the</token>
<token id="t_24" lemma="name" pos="NNS">names</token>
<token id="t_25" lemma="I" pos="PP">I</token>
<token id="t_26" lemma="will" pos="MD">will</token>
<token id="t_27" lemma="call" pos="VV">call</token>
<token id="t_28" lemma="out" pos="RP">out</token>
<token id="t_29" lemma="." pos="SENT">.</token>
</s>
</p>
</div>
</text>
这是我想要的输出:
<text>
<div id="d_1">
<p id="p_1">
<s id="s_1">
<token id="t_13" lemma="colleague" pos="NN">Colleagues</token>
<token id="t_14" lemma="," pos=",">,</token>
<e>
<token id="t_15" lemma="we" pos="PP">we</token>
<token id="t_16" lemma="now" pos="RB">now</token>
</e>
<token id="t_17" lemma="come" pos="VVP">come</token>
<token id="t_18" lemma="to" pos="TO">to</token>
<token id="t_19" lemma="catch-the-eye" pos="NN">catch-the-eye</token>
<token id="t_20" lemma="." pos="SENT">.</token>
</s>
<s id="s_2">
<token id="t_21" lemma="these" pos="DT">These</token>
<token id="t_22" lemma="be" pos="VBP">are</token>
<token id="t_23" lemma="the" pos="DT">the</token>
<token id="t_24" lemma="name" pos="NNS">names</token>
<token id="t_25" lemma="I" pos="PP">I</token>
<token id="t_26" lemma="will" pos="MD">will</token>
<token id="t_27" lemma="call" pos="VV">call</token>
<token id="t_28" lemma="out" pos="RP">out</token>
<token id="t_29" lemma="." pos="SENT">.</token>
</s>
</p>
</div>
</text>
这是我正在使用的样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="no"></xsl:output>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"></xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:variable name="dif_tok">
<dif_tok>t_15</dif_tok>
<dif_tok>t_16</dif_tok>
</xsl:variable>
<xsl:template match="s">
<xsl:copy>
<xsl:apply-templates select="@*"></xsl:apply-templates>
<e>
<xsl:copy-of select="*[@id = $dif_tok/dif_tok]"></xsl:copy-of>
</e>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这就是我最终获得的结果:
<text>
<div id="d_1">
<p id="p_1">
<s id="s_1"><e><token id="t_15" lemma="we" pos="PP">we</token><token id="t_16" lemma="now" pos="RB">now</token></e></s>
<s id="s_2"><e/></s>
</p>
</div>
</text>
答案 0 :(得分:0)
具有特定属性的某些元素应该是新元素的子元素
编写单独的模板以匹配您感兴趣的token
元素。
<xsl:template match="token[@id ='t_15']">
在模板中,生成e
元素,并利用apply-templates
的行为将其填充到@id = t_15 and t_16
的标记中。然后,让身份变换完成所有其余的工作。
<强>样式表强>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="token[@id ='t_15']">
<e>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::token[1]"/>
</e>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
<?xml version="1.0" encoding="UTF-8"?>
<text>
<div id="d_1">
<p id="p_1">
<s id="s_1">
<token id="t_13" lemma="colleague" pos="NN">Colleagues</token>
<token id="t_14" lemma="," pos=",">,</token>
<e>
<token id="t_15" lemma="we" pos="PP">we</token>
<token id="t_16" lemma="now" pos="RB">now</token>
</e>
<token id="t_16" lemma="now" pos="RB">now</token>
<token id="t_17" lemma="come" pos="VVP">come</token>
<token id="t_18" lemma="to" pos="TO">to</token>
<token id="t_19" lemma="catch-the-eye" pos="NN">catch-the-eye</token>
<token id="t_20" lemma="." pos="SENT">.</token>
</s>
<s id="s_2">
<token id="t_21" lemma="these" pos="DT">These</token>
<token id="t_22" lemma="be" pos="VBP">are</token>
<token id="t_23" lemma="the" pos="DT">the</token>
<token id="t_24" lemma="name" pos="NNS">names</token>
<token id="t_25" lemma="I" pos="PP">I</token>
<token id="t_26" lemma="will" pos="MD">will</token>
<token id="t_27" lemma="call" pos="VV">call</token>
<token id="t_28" lemma="out" pos="RP">out</token>
<token id="t_29" lemma="." pos="SENT">.</token>
</s>
</p>
</div>
</text>
您尝试的解决方案使用变量。这也是一个很好的方法:
<xsl:variable name="start" select="'t_15'"/>
<xsl:template match="token[@id=$start]">
<e>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::token[1]"/>
</e>
</xsl:template>
答案 1 :(得分:0)
我稍微修改了Mathias制作的样式表。见下文。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="start" select="'t_15'"/>
<xsl:variable name="middle" select="'t_16'"/>
<xsl:variable name="end" select="'t_17'"/>
<xsl:template match="token[@id =$start]">
<e>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::token[@id=$middle]" mode="group"/>
<xsl:apply-templates select="following-sibling::token[@id=$end]" mode="group"/>
</e>
</xsl:template>
<xsl:template match="token[@id =$middle]|token[@id =$end]" mode="group">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="token[@id =$middle]|token[@id =$end]"/>
</xsl:stylesheet>
答案 2 :(得分:0)
编辑:因为我写了这个答案,问题已经改为需要XSLT 1.0而不是2.0,但我会在这里留下答案供参考。
由于您使用的是XSLT 2.0,因此这是group-adjacent
for-each-group
机制的理想情况。假设您拥有以前的身份模板,那么
<xsl:variable name="tokensToGroup" select="('t_15', 't_16')" />
<xsl:template match="s">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each-group select="token" group-adjacent="@id = $tokensToGroup">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<e><xsl:apply-templates select="current-group()" /></e>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
其ID与$tokensToGroup
匹配的相邻令牌将被收集到current-grouping-key()
值为布尔true
的单个组中,其他令牌将被收集到密钥为{{1}的组中我们只使用false
键在<e>...</e>
周围包裹true
。
如果不是要分组的所有ID的列表,而是只有第一个和最后一个令牌的ID,那么您可以使用相同的机制,但使用不同的分组键定义
<xsl:param name="first" select="'t_15'" />
<xsl:param name="last" select="'t_17'" />
<xsl:for-each-group select="token"
group-adjacent="( (. | preceding-sibling::token)[@id = $first] and
(. | following-sibling::token)[@id = $last] )">
此处true
键值适用于在$firstToken
之前或之前$lastToken
和之后的元素。假设处理器尚未对其进行优化,例如
<xsl:key name="tokenById" match="token" use="@id" />
<xsl:variable name="firstToken" select="key('tokenById', $first)" />
<xsl:variable name="lastToken" select="key('tokenById', $last)" />
<xsl:for-each-group select="token"
group-adjacent="( (. is $firstToken or . >> $firstToken) and
(. is $lastToken or . << $lastToken) )">