繁体   English   中英

在父级之间移动xml节点并删除重复项-xslt 2.0

[英]Move xml nodes between parents and delete duplicates - xslt 2.0

我有一个xml,如下所示,想1)如果属性名称匹配,则将“数据”节点中的值移至“标头”,或2)如果名称属性与使用xsl转换的标头中的现有节点相同,则删除“数据”下的节点, 如果可能的话。 任何帮助将不胜感激。

初始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>

如果子节点5是要移动的节点,则结果为...转换后:

<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')]"/>

有很多方法可以进行这种转换,但是在这种情况下,我认为明智的选择是使用xslt 键功能,请参见此处的简要说明。

<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>

为简单起见,上面的样式表不会按字母顺序对标题键进行排序,如果确实需要,则必须进行执行排序

我试图保留尽可能多的原始样式表,但是按照这种方式,我没有找到其他解决方案。

如果要按@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>

希望这可以帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM