我有一个xml如下所示,并希望1)如果匹配属性名称,则将数据节点中的值移动到Header;或者2)如果name属性与标题中的现有节点相同,则删除Data下的节点如果可能的话,使用xsl tranform。任何帮助将不胜感激。
初始xml:
<HEADER>
<KEY name="child1" value="value1" />
<KEY name="child2" value="value2" />
<KEY name="child3" value="value3" />
<KEY name="child4" value="value4" />
</HEADER>
<DATA>
<KEY name="child1" value="value1.data" />
<KEY name="child3" value="value3.data" />
<KEY name="child5" value="value5" />
<KEY name="child7" value="value7" />
</DATA>
如果Child 5是要移动的节点,则结果为...... After Transform:
<HEADER>
<KEY name="child1" value="value1" />
<KEY name="child2" value="value2" />
<KEY name="child3" value="value3" />
<KEY name="child4" value="value4" />
<KEY name="child5" value="value5" />
</HEADER>
<DATA>
<KEY name="child7" value="value7" />
</DATA>
当前xsl:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output omit-xml-declaration="no" method="xml" indent="yes" />
<!-- <xsl:variable name="ReplaceLiveDate" select="false()" /> -->
<xsl:variable name="ReplaceLiveDate" select="true()" />
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<!-- base identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- in HEADER: output ROLE sorted by @name -->
<xsl:template match="HEADER">
<xsl:copy>
<xsl:apply-templates select="KEY">
<xsl:sort select="translate(@name, $smallcase, $uppercase)" order="ascending" />
<!-- <xsl:sort select="@name" /> -->
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- in DATA: output KEY sorted by @name -->
<xsl:template match="DATA">
<xsl:copy>
<xsl:apply-templates select="KEY">
<xsl:sort select="translate(@name, $smallcase, $uppercase)" order="ascending" />
<!-- <xsl:sort select="@name" /> -->
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
我有以下内容删除节点,但不确定如果节点存在于标题部分中如何才能执行此操作
<!-- remove processing nodes -->
<xsl:template match="KEY[starts-with(@name, 'child1')]"/>
答案 0 :(得分:1)
有很多方法可以进行转换,但在这种情况下,我认为聪明的方法是使用xslt 键功能,请参阅here进行简要说明
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output omit-xml-declaration="no" method="xml" indent="yes" />
<!-- <xsl:variable name="ReplaceLiveDate" select="false()" /> -->
<xsl:variable name="ReplaceLiveDate" select="true()" />
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<!-- index all the KEY element of the HEADER -->
<xsl:key name='head' match='HEADER/KEY' use='@name' />
<!-- base identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match='HEADER'>
<xsl:copy>
<!-- move the child5 'KEY element' under the header -->
<xsl:copy-of select="//DATA/KEY[@name = 'child5']"/>
<!-- apply to childs -->
<xsl:apply-templates select="KEY">
<xsl:sort select="translate(@name, $smallcase, $uppercase)" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- delete key nodes duplicated in Header, that is elments not indexed by the 'head' key -->
<xsl:template match="DATA/KEY[key('head',@name)]">
</xsl:template>
<!-- delete the node to be moved -->
<xsl:template match="DATA/KEY[@name = 'child5']" />
</xsl:stylesheet>
为简单起见,上面的样式表不会按字母顺序对标题键进行排序,如果确实需要,则需要perform-sort。
我尽量保留原始样式表,但我没有找到任何其他解决方案。
如果您希望按@name属性
排序键,则在模板下方<xsl:template match='HEADER'>
<xsl:variable name='unsorted_keys'>
<xsl:copy-of select="//DATA/KEY[@name = 'child5']"/>
<!-- apply to childs -->
<xsl:apply-templates select="KEY">
</xsl:apply-templates>
</xsl:variable>
<xsl:copy>
<!-- make sure to copy HEADER attributes -->
<xsl:apply-templates select='@*'/>
<!-- perform sort -->
<xsl:perform-sort select="$unsorted_keys/KEY">
<xsl:sort select="translate(@name, $smallcase, $uppercase)" order="ascending" />
</xsl:perform-sort>
</xsl:copy>
</xsl:template>
希望这有帮助