2012-09-07 54 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

相关问题