1

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"
4

1 に答える 1

5

この変換は実行できます。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' に変換します。

于 2013-02-26T16:22:57.220 に答える