2012-09-07 90 views
0

我需要將以下XML轉換爲具有相同元素和屬性的XML,但可以本地化的值(基本上是英語短語)除外。XSL僅用於將XML元素和屬性值過濾出來?

一些元素(<footnote>)和屬性是可選的(<display_data_type>),我希望能夠做到這一般 - 沒有每個元素的模板。那可能嗎?

最終目標是能夠將默認版本的XML與本地化版本進行比較,而忽略本地化字符串。

例如以下:

<data_schema> 
    <field symbol="ACCOUNT" type="string" name="Account Number"> 
     <validators> 
      <maxlength>6</maxlength> 
     </validators> 
     <description>The account number</description> 
     <example>123456</example> 
     <default_value></default_value> 
    </field> 
    <field symbol="POSTAL_CODE" type="string" name="Postal Code"> 
     <description>Postal Code for account</description> 
     <example>22022</example> 
     <footnote>Does not apply to certain accounts</footnote> 
     <default_value></default_value> 
    </field> 
    <field symbol="DISCOUNT" type="string" name="Discount Percentage" display_data_type="percentage"> 
     <description>Descount determined by account</description> 
     <example>1.5%</example> 
     <default_value></default_value> 
    </field> 
</data_schema> 

將被轉換成:

<data_schema> 
    <field symbol="ACCOUNT" type="string" name=""> 
     <validators> 
      <maxlength>6</maxlength> 
     </validators> 
     <description/> 
     <example/> 
     <default_value/> 
    </field> 
    <field symbol="POSTAL_CODE" type="string" name=""> 
     <description/> 
     <example/> 
     <footnote/> 
     <default_value/> 
    </field> 
    <field symbol="DISCOUNT" type="string" name="" display_data_type="percentage"> 
     <description/> 
     <example/> 
     <default_value/> 
    </field> 
</data_schema> 
+0

這對於本地化的問題沒有關係。任何排除任何元素或屬性的例子都是可以接受的。如果它確實很重要,則示例輸入和輸出指示哪些特定元素是可本地化的。 – Glenn

回答

1

下面是一個例子。像這樣的模板在應用時應該創建樹的副本,減去不是符號或類型的屬性的文本區域和屬性文本。

<xsl:template match="*"> 
    <xsl:element name="{name()}"> 
    <xsl:for-each select="@*"> 
     <xsl:choose> 
     <xsl:when test="name() = 'symbol' or name() = 'type'"> 
      <xsl:copy-of select="."/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:attribute name="{name()}"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 

    <xsl:apply-templates select="*"/> 
    </xsl:element> 
</xsl:template> 
+0

正是我需要的。謝謝! – Glenn

+1

錯誤。顯然,答案海報和OP都沒有測試過這個解決方案。 –

+0

肖恩,你是不正確的 - 這工作,並足夠我的目的。再試一次。 – Glenn

4

這是另一種方法。這個建立在「身份變換」的XSLT設計模式上,因爲它基本上只是複製所有節點。

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

你可以擴展它來添加其他模板匹配,以匹配你想要採取特定動作的節點,在你的情況下是刪除文本。所需的模板將取決於轉換的確切規則。

如果您想從具體的元素和屬性中刪除文本,您將添加以下兩個模板,複製節點,但沒有文字:

<xsl:template match="description|example|footnote|default_value"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="@name"> 
    <xsl:attribute name="{name()}"/> 
</xsl:template> 

因此,在這種情況下,元素描述示例,腳註default_value刪除了它們的文本,以及@name屬性。所有其他節點將按照原樣複製。

在otherhand,那就是你有元素的特定列表和屬性,你想改變,你可以添加模板,像這樣

<xsl:template match="field/*[not(self::validators)]"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="@symbol|@type|@display_data_type"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="@*"> 
    <xsl:attribute name="{name()}"/> 
</xsl:template> 

所以,對於驗證元素,你實際上是在說,刪除一切都不是驗證器元素。元素將被標識轉換模板複製。對於這些屬性,我已經顯示了一種稍微不同的方法,其中要保留的屬性已經被明確列出,並且您有第二個模板來從其他所有文本中刪除文本。

這裏是兩個完整的XSLT在這種情況下。

第一從特定節點

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

    <xsl:template match="description|example|footnote|default_value"> 
     <xsl:copy/> 
    </xsl:template> 

    <xsl:template match="@name"> 
     <xsl:attribute name="{name()}"/> 
    </xsl:template> 

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

第二保持文本中的特定節點

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

    <xsl:template match="field/*[not(self::validators)]"> 
     <xsl:copy/> 
    </xsl:template> 

    <xsl:template match="@symbol|@type|@display_data_type"> 
     <xsl:copy/> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:attribute name="{name()}"/> 
    </xsl:template> 

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

在示例文檔的情況下去除文本,兩者都應該產生相同的輸出:

<data_schema> 
    <field symbol="ACCOUNT" type="string" name=""> 
     <validators> 
     <maxlength>6</maxlength> 
     </validators> 
     <description/> 
     <example/> 
     <default_value/> 
    </field> 
    <field symbol="POSTAL_CODE" type="string" name=""> 
     <description/> 
     <example/> 
     <footnote/> 
     <default_value/> 
    </field> 
    <field symbol="DISCOUNT" type="string" name="" display_data_type="percentage"> 
     <description/> 
     <example/> 
     <default_value/> 
    </field> 
</data_schema> 
+0

謝謝蒂姆。非常有用的解釋。我的主要目標是簡單地提供最簡潔和可理解的xslt,而不必爲每個可本地化的屬性/元素提供單獨的模板。 – Glenn

相關問題