2013-05-22 81 views
0

我有一個XML文檔,其中包含有關父實體的用戶定義信息。我想創建一個XSLT將XML轉換爲當前用戶定義的列表。 XSLT將需要忽略已移除的元素,添加新元素並保留用戶定義的元素順序。使用XSLT添加和刪除XML元素

例輸入XML:

<InventoryProperties> 
     <InvProp Name="Weight" 
       Type="Text" 
       Alignment="Right">12500</InvProp> 
     <InvProp Name="Length" 
       Type="Text" 
       Alignemnt="Right">20.2</InvProp> 
     <InvProp Name="GVW" 
       Type="Text"></InvProp> 
    </InventoryProperties> 

所以,現在的用戶已經改變了收集的數據點,並且不希望GVW了,但增加了身高體重和體長之間。什麼到目前爲止,我所做的就是這樣來我想要的元素和離開我不再需要的元素背後:

<xsl:apply-templates select="InventoryProperties/InvProp[@Name = 'Weight']"/> 

重複的是當前定義的每個領域。這工作正常,並保持預期的順序。對於加入新的元素,我想是這樣的:

<xsl:apply-templates select="InventoryProperties[not(InvProp[@Name='Height'])]"/> 
<xsl:template name="HeightTemplate" 
       match="InventoryProperties[not(InvProp[@Name='Height'])]"> 

    <xsl:apply-templates select="@*[not(name()='Height')]|node()"/> 

    <Property LabelText="HelloWorld" /> 
    </xsl:template> 

而且這幾個其他版本,但沒有什麼是生產什麼,我想這將是:

<InventoryProperties> 
    <Property LabelText="Weight" 
      ControlType="Text">12500</Property> 
    <Property LabelText="Height" 
      ControlType="Text"></Property> 
    <Property LabelText="Length" 
      ControlType="Text">20.2</Property> 
</InventoryProperties> 

沒有理由元素和屬性名稱的改變,我只是想分清什麼是工作,什麼不是。

+0

我不確定是否正確理解這一點。樣式表(在你的例子中)應該忽略Name =「GVW」的元素,並在Name後面添加一個名稱爲「Height」的元素,如果它還沒有一個呢? –

+0

@ hr_117 - 是的,這是正確的。在這個例子中,Xml是在最新定義之前保存的,所以當數據現在呈現給最終用戶時,我們需要顯示當前數據點,但不包括GVW,但是包括Height。 –

回答

0

我建議您爲要添加到輸出的每個字段名稱調用一個命名模板。該命名模板將檢查是否存在具有給定Name屬性的元素,如果存在,則複製該元素,如果不是,則創建具有正確屬性的存根。

這給出了這個概念

<xsl:template match="InventoryProperties"> 
    <xsl:call-template name="inv-prop"> 
    <xsl:with-param name="name" select="'Weight'"/> 
    </xsl:call-template> 
    <xsl:call-template name="inv-prop"> 
    <xsl:with-param name="name" select="'Height'"/> 
    </xsl:call-template> 
    <xsl:call-template name="inv-prop"> 
    <xsl:with-param name="name" select="'Length'"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="inv-prop"> 
    <xsl:param name="name"/> 
    <xsl:variable name="selection" select="InvProp[@Name = $name]"/> 
    <xsl:choose> 
    <xsl:when test="$selection"> 
     <xsl:copy-of select="$selection"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <InvProp Name="{$name}" Type="Text" Alignment="Right"> 
     <xsl:value-of select="InvProp[@Name = $name]"/> 
     </InvProp> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

輸出

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <InvProp Name="Weight" Type="Text" Alignment="Right">12500</InvProp> 
    <InvProp Name="Height" Type="Text" Alignment="Right"/> 
    <InvProp Name="Length" Type="Text" Alignemnt="Right">20.2</InvProp> 
</root> 
+0

有趣的是,我非常喜歡應用模板,我沒有考慮過這種情況,唯一的缺點就是在這種情況下沒有「存根」或默認值,每個屬性的值對每個元素都是唯一的,爲了簡潔,我省略了幾個屬性。在你的例子中,你對Type和Alignment的值進行了硬編碼,我不能這樣做,我添加了更多的參數來傳遞其他參數價值觀,這似乎工作,我很好奇儘管如此,鑑於我的新情況,你還會使用相同的解決方案嗎? –

0

也許你應該試試這個。
身份轉換與一些掛鉤忽略或添加元素。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <!-- ingnore not wonted stuff --> 
    <xsl:template match ="InvProp[@Name='GVW'] " /> 

    <!-- add missing stuff --> 
    <xsl:template match ="InvProp[@Name='Weight'] "> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
     <xsl:if test="not(following-sibling::InvProp[@Name='Height'])" > 
      <InvProp Name="Height" Type="Text" Alignment="Right"/> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet>