假设我在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"
答案 0 :(得分:5)
这种转变可以完成。我假设你使用的是XSLT 1.0,XSLT 2.0中的解决方案会更短(因为我必须做的递归模板才能实现2)。我也假设:
代码的想法是手动匹配每个属性并将其值替换为正确的值。因为我不知道遵循所有属性的逻辑(除了我在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'。