繁体   English   中英

使用XSL将XML转换为XAML

[英]Transform XML to XAML with XSL

可以说我在xml中有以下代码片段:

<PanelWrapper   id="RootPanel" 
                dock="Fill" 
                width="1092" 
                height="605" 
                backcolor="Transparent" 
                visible="True">
    <ButtonWrapper  id="button1" 
                    dock="Left" 
                    text="TestButton" 
                    width="75" 
                    height="605" 
                    border-left="1" 
                    border-top="1" 
                    border-right="1" 
                    border-bottom="1" 
                    font-name="Tahoma" 
                    font-size="9" 
                    font-style="Regular">
    </ButtonWrapper>
</PanelWrapper>

我需要将xml代码转换为XAML。 预期的最终结果应如下所示:

<WrapPanel Name="RootPanel" 
           DockPanel.Dock="Left, Right, Top, Bottom" 
           Width="1092" Height="605" 
           Background="Transparent"  
           Visibility="Visible">
    <Button Name="button1" 
            DockPanel.Dock ="Left" 
            Content="TestButton" 
            Width="75" 
            Height="605" 
            BorderThickness="1,1,1,1" 
            FontFamily="Tahoma" 
            FontSize="9" 
            FontStyle="Normal">
    </Button>
</WrapPanel>

xsl样式表可以进行这种转换吗?

我特别在问这样的转换:

border-left="1" 
border-top="1" 
border-right="1" 
border-bottom="1"

BorderThickness="1,1,1,1" 

或来自

visible="True"

Visibility="Visible"

可以完成此转换。 我假设您使用的是XSLT 1.0,那么XSLT 2.0中的解决方案会更短(因为要实现2,我必须要做递归模板)。 我还假设:

  1. Visible的可能值是:“ True”,“ False”,它们分别转换为“ Visible”和“ Hidden”。
  2. BorderThickness属性按以下顺序构建:左,上,右,下。 此外,如果未找到某些边框属性,则其值默认为零。

代码的思想是手动匹配每个属性,并将其值替换为正确的值。 因为我不知道遵循所有属性的逻辑(除了我在1.和2中假定的位),所以转换仅限于给定的XML,但是我希望它能为您提供实现目标的思路试图做。

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

    <!-- Ignore attributes by default, so we can have more control
         about unhandled attributes -->
    <xsl:template match="@*" />

    <!-- 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>

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

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

    <!-- For every other @dock value, map @dock to DockPanel.dock
         and copy value --> 
    <xsl:template match="@dock">
        <xsl:attribute name="DockPanel.Dock">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>

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

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

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

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

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

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

    <!-- Build the border attribute -->
    <xsl:template match="@*[starts-with(local-name(), 'border-')][1]">
        <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">
        <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>


    <!-- Map font properties -->
    <xsl:template match="@font-name">
        <xsl:attribute name="FontFamily">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@font-size">
        <xsl:attribute name="FontSize">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@font-style[. = 'Regular']">
        <xsl:attribute name="FontStyle">Normal</xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

该代码的主要思想是:

  • 您可以使用以下模板来更改元素的名称:

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

    它匹配名为PanelWrapper的任何元素,并将其名称更改为WrapPannel。

  • 您可以使用以下模板更改属性名称并保留其值:

     <xsl:template match="@font-size"> <xsl:attribute name="FontSize"> <xsl:value-of select="." /> </xsl:attribute> </xsl:template> 

    它将属性font-size映射到FontSize。

  • 您可以通过匹配属性的名称和值来更改其名称和值,例如:

     <xsl:template match="@font-style[. = 'Regular']"> <xsl:attribute name="FontStyle">Normal</xsl:attribute> </xsl:template> 

    匹配所有属性,例如font-style ='regular'并将其转换为FontStyle ='normal'。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM