使用 XSLT 1.0 将 XML 转换为 XAML |排除某些控件的特定转换 [英] XML to XAML transformation using XSLT 1.0 | Exclude specific transformations for some controls

查看:14
本文介绍了使用 XSLT 1.0 将 XML 转换为 XAML |排除某些控件的特定转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下 XML 代码

Let say I have the following XML Code

<PanelWrapper   id="RootPanel" 
                width="800" 
                height="600" 
                forecolor="Black">
    <ButtonWrapper  id="button" 
                    text="click!" 
                    forecolor="Black">
        <TabIndex>0</TabIndex>
        <TabStop>True</TabStop>
    </ButtonWrapper>
</PanelWrapper>

应使用 XSLT 1.0 将此代码转换为 XAML 代码:

This Code should be transformed into XAML Code using XSLT 1.0:

<WrapPanel Name="RootPanel" 
           Width="800" 
           Height="600">
    <Button Name="button" 
            Content="click!" 
            Foreground="Black"  
            TabIndex="0" 
            IsTabStop="True">
    </Button>
</WrapPanel>

我目前正在使用这个样式表:(简化版)

I'm currently using this Style sheet: (simplified version)

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

    <!-- Transform PanelWrapper to WrapPannel -->
    <xsl:template match="PanelWrapper">
        <WrapPanel>
            <xsl:apply-templates select="@*|*" />
        </WrapPanel>
    </xsl:template>

    <!-- Transform ButtonWrapper to Button -->
    <xsl:template match="ButtonWrapper">
        <Button>
            <xsl:apply-templates select="@*" />
        </Button>
    </xsl:template>

    <!-- some other mapping for id(name), height, weight, text -->

    <!-- Map forecolor to Foreground -->
    <xsl:template match="@forecolor">
        <xsl:attribute name="Foreground">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

我目前得到的结果如下:

The result I'm currently getting looks like this:

<WrapPanel Name="RootPanel" 
           Width="800" 
           Height="600"
           Foreground="Black"> //unwanted, Problem 1
    <Button Name="button" 
            Content="click!" 
            Foreground="Black">
    </Button>
            0 //Problem 2
        True //Problem 2
</WrapPanel>

问题 1:XAML 中的 WrapPanel 没有 Foreground 属性,但由于在我的 XML 源文件中定义了前景色,因此它也是为 WrapPanel 生成的.我该如何解决这个问题?

Problem 1: The WrapPanel in XAML has no Foreground Property but since the there is an forecolor defined in my XML source file it is generated for the WrapPanel too. How can I solve this?

问题 2:如何解决 TabIndex 和 IsTabStop 的问题?

Problem 2: How can I fix the issue with the TabIndex and IsTabStop?

让我澄清问题 2.这是 xml 输入:

Let me clarify problem 2. this is the xml input:

<ButtonWrapper  id="button" 
                text="click!" 
                forecolor="Black">
    <TabIndex>0</TabIndex>
    <TabStop>True</TabStop>
</ButtonWrapper>

这是我尝试实现的输出:

and this is the output i try to achieve:

<Button Name="button" 
        Content="click!" 
        Foreground="Black"  
        TabIndex="0" 
        IsTabStop="True">
</Button>

推荐答案

问题 1.您可以添加以下模板

<xsl:template match="PanelWrapper/@forecolor" />

这将排除所有 PanelWrapper 元素的名为 forecolor 的属性.

which is going to exclude the attributes named forecolor for all the PanelWrapper elements.

问题 2.要解决您的第二个问题,您必须分别使用以下 XPath 表达式匹配所有 TabIndex 元素和 TabStop 元素,它们是某个元素的子元素:*/TabIndex、*/TabStop.然后您可以将该元素映射到一个属性.

Problem 2. To solve your second problem you have to match all TabIndex elements and TabStop elements which are children of some element using the following XPath expressions respectively : */TabIndex, */TabStop. Then you can map that element to an attribute.

以下转换实现了您想要的:

The following transformation achieves what you want:

<!-- Transform element TabIndex to an attribute with the same
     name in its parent -->
<xsl:template match="*/TabIndex">
    <xsl:attribute name="TabIndex">
        <xsl:value-of select="." />
    </xsl:attribute>
</xsl:template>

<!-- Transform element TabStop to an attribute with the name
     IsTabStop in its parent -->
<xsl:template match="*/TabStop">
    <xsl:attribute name="IsTabStop">
        <xsl:value-of select="." />
    </xsl:attribute>
</xsl:template>

<小时>

更新.添加了完整 XML 的解决方案.


UPDATE. Added solution for complete XML.

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

    <xsl:variable name="attributeMap"
                  select="'|font-size,FontSize|font-name,FontFamily|enabled,isEnabled|forecolor,Foreground|id,name|TabStop,IsTabStop|TabIndex,isTabIndex|dock,DockPanel.Dock|width,Width|height,Height|'" />

    <!--                        -->
    <!-- Default processing     -->
    <!--                        -->

    <!-- Ignore attributes by default, so we can have more control
         about unhandled attributes -->
    <xsl:template match="@*|*" />
    <xsl:template match="node()|@*" mode="to-attr"/>

    <!-- Default attribute processing -->
    <xsl:template name="process-element">
        <xsl:param name="attr" />

        <!-- Process all attributes and elements which are going to be
             transformed to attributes -->
        <xsl:apply-templates select="@*|*" mode="to-attr" />
        <!-- Add extra attribute -->
        <xsl:if test="$attr">
            <xsl:attribute name="{substring-after($attr, '|')}">
                <xsl:value-of select="@*[local-name() = substring-before($attr, '|')]" />
            </xsl:attribute>
        </xsl:if>
        <!-- Process children elements -->
        <xsl:apply-templates select="*" />
    </xsl:template>

    <!--                        -->
    <!-- Control transformations-->
    <!--                        -->

    <!-- Transform PanelWrapper to WrapPannel -->
    <xsl:template match="PanelWrapper">
        <WrapPanel>
            <xsl:call-template name="process-element" />
        </WrapPanel>
    </xsl:template>

    <!-- Exclude attributes for PanelWrapper -->
    <xsl:template match="PanelWrapper/@forecolor|PanelWrapper/@font-name|PanelWrapper/@font-size|PanelWrapper/@font-style"
                  mode="to-attr" />
    <!-- TODO: Exclude doesn't work for the following attributes -->
    <xsl:template match="PanelWrapper/@border-left|PanelWrapper/@border-top|PanelWrapper/@border-right|PanelWrapper/@border-bottom"
                  mode="to-attr"  />

    <!-- Transform DropDownWrapper to ComboBox -->
    <xsl:template match="DropDownWrapper">
        <ComboBox>
            <xsl:call-template name="process-element">
                <xsl:with-param name="attr" select="'text|Text'" />
            </xsl:call-template>
        </ComboBox>
    </xsl:template>

    <!-- Exclude attributes for ComboBox -->
    <!-- Transform GroupBoxWrapper to GroupBox -->

    <!-- Map GroupBoxWrapper, LabelWrapper, TextBoxWrapper, ButtonWrapper into
         elements with their prefix as their name -->
    <xsl:template match="GroupBoxWrapper|LabelWrapper|TextBoxWrapper|ButtonWrapper">
        <xsl:element name="{substring-before(local-name(), 'Wrapper')}">
            <xsl:call-template name="process-element">
                <xsl:with-param name="attr" select="'text|Content'" />
            </xsl:call-template>
        </xsl:element>
    </xsl:template>

    <!-- Exclude attributes for GroupBox -->
    <!-- Exclude attributes for Label -->
    <!-- Exclude attributes for Text -->
    <!-- TODO: invalid value for Background attribute, eg: Background="window" -->
    <!-- Exclude attributes for Button -->
    <!-- TODO: invalid value for Background attribute, eg: Background="buttonface" -->


    <!-- Map RadioButtonViewWrapper, CheckBoxViewWrapper into elements
         with their prefix as their name -->
    <xsl:template match="RadioButtonViewWrapper|CheckBoxViewWrapper">
        <xsl:element name="{substring-before(local-name(), 'ViewWrapper')}">
            <xsl:call-template name="process-element">
                <xsl:with-param name="attr" select="'text|Content'" />
            </xsl:call-template>
        </xsl:element>
    </xsl:template>


    <!-- Exclude attributes for RadioButton -->
    <!-- Exclude attributes for CheckBox -->


    <!--                           -->
    <!-- Attributes transformations-->
    <!--                           -->

    <!-- Transform elements which just map the name of the attribute to a different name -->
    <xsl:template match="@font-size|@font-name|@enabled|@forecolor|@id|TabStop|TabIndex|@dock|@width|@height"
                  mode="to-attr">
        <!-- Look in map for the transformation -->
        <xsl:variable name="new-attribute"
                      select="substring-before(substring-after($attributeMap, concat('|', local-name(), ',')), '|')" />
        <xsl:attribute name="{$new-attribute}">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>

    <!-- OVERRIDE!! Back color: not sure of the logic here.-->
    <xsl:template match="@backcolor" mode="to-attr">
        <xsl:attribute name="Background">Grey</xsl:attribute>
    </xsl:template>

    <!-- Ignore TabIndex and TabStop within PanelWrapper -->
    <xsl:template match="PanelWrapper/TabIndex|PanelWrapper/TabStop" mode="to-attr" />

    <!-- Map @dock = 'Fill' to @dock = 'Left, Right...etc' -->
    <xsl:template match="@dock[. = 'Fill']"  mode="to-attr" >
        <xsl:attribute name="DockPanel.Dock">
            <xsl:value-of select="'Left, Right, Top, Bottom'" />
        </xsl:attribute>
    </xsl:template>

    <!-- Map visible attribute to Visibility -->
    <xsl:template match="@visible[. = 'True']"  mode="to-attr" >
        <xsl:attribute name="Visibility">visible</xsl:attribute>
    </xsl:template>

    <xsl:template match="@visible[. = 'False']"  mode="to-attr" >
        <xsl:attribute name="Visibility">hidden</xsl:attribute>
    </xsl:template>

    <!-- Build the border attribute -->
    <xsl:template match="@*[starts-with(local-name(), 'border-')][1]"  mode="to-attr">
        <xsl:attribute name="BorderThickness">
            <!-- Print the border-elements in a comma separated list (non-defined attributes default
                 to zero) -->
            <xsl:call-template name="border-print" />
        </xsl:attribute>
    </xsl:template>

    <!-- Recursive template to group borders in BorderThickness -->
    <xsl:template name="border-print">
        <!-- Do not remove spaces in the next line! -->
        <xsl:param name="string" select="'left  top   right bottom'" />
        <xsl:param name="parent" select=".." />
        <xsl:param name="not-first" select="false()" />

        <xsl:if test="$string != ''">
            <!-- Obtain next direction -->
            <xsl:variable name="direction" select="normalize-space(substring($string, 1, 6))" />
            <xsl:variable name="attr" select="$parent/@*[local-name() = concat('border-', $direction)]" />
            <!-- Print comma if not the first element -->
            <xsl:if test="$not-first"><xsl:text>,</xsl:text></xsl:if>
            <!-- Print zero if the attribute cannot be found -->
            <xsl:choose>
                <!-- Attribute found : print -->
                <xsl:when test="$attr">
                    <xsl:value-of select="$attr" />
                </xsl:when>
                <!-- Attribute not found: print 0 -->
                <xsl:otherwise>
                    <xsl:text>0</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
            <!-- Recurse -->
            <xsl:call-template name="border-print">
                <xsl:with-param name="string" select="substring($string, 7)" />
                <xsl:with-param name="parent" select="$parent" />
                <xsl:with-param name="not-first" select="true()" />
            </xsl:call-template>
        </xsl:if>

    </xsl:template>

    <xsl:template match="@*" mode="print-border">
        <xsl:value-of select="concat(., ',')" />
    </xsl:template>

    <xsl:template match="@border-bottom" mode="print-border">
        <xsl:value-of select="." />
    </xsl:template>

    <!--
    <xsl:template match="@font-style[. = 'Regular']">
        <xsl:attribute name="FontStyle">Normal</xsl:attribute>
    </xsl:template>
    -->
    <!-- TODO: condition is invalid, chooses Italic for everything-->
    <xsl:template match="@font-style"  mode="to-attr">
        <xsl:choose>
            <xsl:when test="'Italic'">
                <xsl:attribute name="FontStyle">Italic</xsl:attribute>
            </xsl:when>
            <xsl:otherwise>
                <xsl:attribute name="FontStyle">Normal</xsl:attribute>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

这篇关于使用 XSLT 1.0 将 XML 转换为 XAML |排除某些控件的特定转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆