鉴于此xml
<?xml version="1.0"?>
<root>
<lev1>
<source id="1"/>
<target id="1"/>
</lev1>
<lev1>
<source id="2"/>
<sometag/>
<lev2>
<sometag/>
<target id="2"/>
<target id="4"/>
</lev2>
<source id="4"/>
<sometag/>
<source id="5"/>
<lev2>
<target id="6"/>
</lev2>
</lev1>
</root>
我想重新编号所有source/@id
值,并使用更新后的值更新任何匹配的target/@id
。我希望所有节点都保留其原始位置,并且我想生成一个注释,其中找不到匹配的target/@id
。
这个xslt是我的出发点:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kTarget" match="target" use="@id"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="source">
<xsl:variable name="newId">
<xsl:number from="/" level="any"/>
</xsl:variable>
<newsource>
<xsl:attribute name="id"><xsl:value-of select="$newId"/></xsl:attribute>
</newsource>
<xsl:call-template name="renumTarget">
<xsl:with-param name="newId"><xsl:value-of select="$newId"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="target"/>
<xsl:template name="renumTarget">
<xsl:param name="newId"/>
<xsl:comment>new id : <xsl:value-of select="$newId"/> old id : <xsl:value-of select="@id"/></xsl:comment>
<xsl:element name="newtarget">
<xsl:attribute name="id"><xsl:value-of select="$newId"/></xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我可以选择旧值和新值......但无法放置新节点。这也不能识别不存在匹配的@id的区域。
有没有办法在xslt中创建某种具有oldVal-&gt; newVal函数的地图?
谢谢!
答案 0 :(得分:1)
我不确定您是否要分别为h1
生成source
的评论而没有相应的newsource
或target
而没有target
,以下内容生成:
source
当应用于输入样本时,我得到输出
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="kTarget" match="target" use="@id"/>
<xsl:key name="kSource" match="source" use="@id"/>
<xsl:template match="node() | @*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="source" mode="number">
<xsl:number level="any"/>
</xsl:template>
<xsl:template match="source">
<xsl:variable name="newId">
<xsl:apply-templates select="." mode="number"/>
</xsl:variable>
<newsource id="{$newId}"/>
<xsl:if test="not(key('kTarget', @id))">
<xsl:comment>
<xsl:value-of select="concat('No target for old id ', @id, ' replaced by ', $newId)"/>
</xsl:comment>
</xsl:if>
</xsl:template>
<xsl:template match="target[key('kSource', @id)]">
<xsl:variable name="changed-id">
<xsl:apply-templates select="key('kSource', @id)" mode="number"/>
</xsl:variable>
<target id="{$changed-id}"/>
</xsl:template>
<xsl:template match="target[not(key('kSource', @id))]">
<xsl:call-template name="identity"/>
<xsl:comment>
<xsl:value-of select="concat('No source for target with id ', @id)"/>
</xsl:comment>
</xsl:template>
</xsl:stylesheet>