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