2014-08-27 84 views
0

我是XSLT新手,但爲工作做了很多XML修改,所以我正在努力學習。我有以下格式輸入XML(有XML上方和下方):刪除與特定節點關聯的所有子元素,並替換爲單個子元素

<Parent Value="x"> 
<!---->Unlimited number of child elements could exist with any value from 0-1 
    <Child Value="0.1"/> 
    <Child Value="1"/> 
    <Child Value="0.30"/> 
    ... 
</Parent> 

我需要在以下格式的父/子節點輸出XML

<Parent Value="x"> 
    <Child Value="0.3"/> 
</Parent> 

哪裏有隻有一個子元素,它的值是0.3。

當前XSLT樣的作品:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Parent"> 
    <Parent> 
     <xsl:apply-templates select="@*|*"/> 
     <Child Value="0.3"/> 
    </Parent> 
</xsl:template> 

<xsl:template match="Child[@Value!=0.3]"/> 

我試圖創建的所有文件所需的子元素(如果它不存在)

<Child Value="0.3"/> 

然後只有在其值= 0.3時才輸出子元素。但是,這有時會導致子節點的重複,並且我覺得我可能沒有以正確的方式處理這個問題。另外,xmlns:xs標題出現在父元素之後,而不是出現在輸出文檔的頂部。任何指導將不勝感激!

電流輸出的例子:

<Parent Value="x" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"> 
    <Child Value="0.30" /> 
    <Child Value="0.3" /> 
</Parent> 

回答

2

只有兩件事情需要修改:

使用單引號的位置:

<xsl:template match="Child[@Value!='0.3']"/> 

如果你不這樣做,值被解釋爲,否則作爲一個字符串。爲什麼這很重要?因爲如果表達式的右側是一個數字,那麼屬性值也會轉換爲一個數字 - 並且0.30.30的結果是相同的。最終導致多個Child元素被輸出。

使用xsl:if有條件地插入Child元素。很明顯,取決於這個特定元素是否已經存在於輸入中。然後,您不會在輸出中獲得兩個Child元素。

注意:Parent不是屬性或元素節點的任何子節點(即processing-instruction()comment())在您的樣式表中被簡單地忽略。這是因爲您僅將模板應用於@*|*,而不是@*|node()

樣式

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Parent"> 
    <Parent> 
     <xsl:apply-templates select="@*|*"/> 
     <xsl:if test="not(Child[@Value = '0.3'])"> 
      <Child Value="0.3"/> 
     </xsl:if> 
    </Parent> 
</xsl:template> 

<xsl:template match="Child[@Value!='0.3']"/> 

</xsl:stylesheet> 

XML輸入

<?xml version="1.0" encoding="UTF-8"?> 
<Parent Value="x"> 
    <Child Value="0.30"/> 
    <Child Value="1"/> 
    <Child Value="0.4"/> 
    <Child Value="0.3">The right one</Child> 
</Parent> 

XML輸出

<Parent xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:fn="http://www.w3.org/2005/xpath-functions" 
     xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" 
     Value="x"> 
    <Child Value="0.3">The right one</Child> 
</Parent> 

目前,有未在輸出XML中使用了命名空間。您可能想要通過將exclude-result-prefixes="#all"添加到xsl:stylesheet來防止它們出現在輸出中。如果你這樣做,那麼輸出簡化爲

<Parent Value="x"> 
    <Child Value="0.3">The right one</Child> 
</Parent> 
+0

我不能告訴你這是多麼有用!這完全有道理。非常感謝! – lcf0285 2014-08-27 17:16:14

0

你是在正確的軌道與基於身份的轉變上,但你可能需要爲一個模板來創建單個子:

<?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" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Child"/> 

<xsl:template match="Parent"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <Child Value="0.3"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet>