我有一个XML文档,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="EDIManagement.Models.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator">
<EntityType Name="AccountRemark">
<Key>
<PropertyRef Name="AccountRemarkId" />
</Key>
<Property Name="AccountRemarkId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="AccountId" Type="int" Nullable="false" />
<Property Name="RemarkTypeId" Type="int" Nullable="false" />
<Property Name="RemarkEnteredAt" Type="datetime" Nullable="false" />
<Property Name="EnteredBy" Type="nvarchar" Nullable="false" MaxLength="100" />
<Property Name="Remark" Type="nvarchar(max)" Nullable="false" />
<Property Name="LastEditedBy" Type="nvarchar" Nullable="false" MaxLength="100" />
</EntityType>
</Schema>
我正在尝试使用XSLT对其进行转换,以便新文档完全相同,只有一行差异。要更改的行是:
<Property Name="Remark" Type="nvarchar(max)" Nullable="false" />
它应该转化为:
<Property Name="Remark" Type="nvarchar" Nullable="false" MaxLength="300" />
到目前为止,我的XSLT转换如下所示:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:def="http://schemas.microsoft.com/ado/2009/02/edm/ssdl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="def:EntityType/def:Property[@Type='nvarchar(max)']/@*" >
<xsl:choose>
<xsl:when test="@Type='nvarchar(max)'">
<xsl:attribute name="Type">nvarchar</xsl:attribute>
<xsl:attribute name="MaxLength">300</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:copy></xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
我正在使用Visual Studio 2010调试逐步完成转换,我发现它正确激活了[@Type='nvarchar(max)']/@*
模板。唯一的问题是xsl:when test="@Type='nvarchar(max)'"
永远不会测试为真。当然这很奇怪,因为如果模板本身匹配,那么这个相同的条件也应该匹配。
但是因为when
测试奇怪地没有成为现实,我的目标根本没有变换,我只是得到了原始文档的精确副本。如果我将when子句更改为xsl:when test="1=1"
,那么它最终会测试为true,这表明整体转换是正确的。但这仍然引出了一个问题:为什么正确的表达永远不会成为现实?
我只是无法弄清楚为什么正确的测试表达式永远不会成真。想法?
答案 0 :(得分:1)
问题在于此代码:
<xsl:template match="def:EntityType/def:Property[@Type='nvarchar(max)']/@*" >
<xsl:choose>
<xsl:when test="@Type='nvarchar(max)'">
<xsl:attribute name="Type">nvarchar</xsl:attribute>
<xsl:attribute name="MaxLength">300</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:copy></xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这一行:<xsl:when test="@Type='nvarchar(max)'">
测试当前(匹配的)节点是否具有名为Type
的具有特定值的属性。但是,只有元素可以具有属性,属性本身永远不具有属性。因此,比较始终为false()
。
一种可能的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl def"
xmlns:def="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match=
"def:EntityType/def:Property
[@Type='nvarchar(max)']" >
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="Type">nvarchar</xsl:attribute>
<xsl:attribute name="MaxLength">300</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<Schema Namespace="EDIManagement.Models.Store"
Alias="Self" Provider="System.Data.SqlClient"
ProviderManifestToken="2008"
xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator">
<EntityType Name="AccountRemark">
<Key>
<PropertyRef Name="AccountRemarkId" />
</Key>
<Property Name="AccountRemarkId" Type="int"
Nullable="false"
StoreGeneratedPattern="Identity" />
<Property Name="AccountId" Type="int"
Nullable="false" />
<Property Name="RemarkTypeId" Type="int"
Nullable="false" />
<Property Name="RemarkEnteredAt" Type="datetime"
Nullable="false" />
<Property Name="EnteredBy" Type="nvarchar"
Nullable="false" MaxLength="100" />
<Property Name="Remark" Type="nvarchar(max)"
Nullable="false" />
<Property Name="LastEditedBy" Type="nvarchar"
Nullable="false" MaxLength="100" />
</EntityType>
</Schema>
产生了想要的正确结果:
<?xml version="1.0" encoding="utf-8"?>
<Schema xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="EDIManagement.Models.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008">
<EntityType Name="AccountRemark">
<Key>
<PropertyRef Name="AccountRemarkId"/>
</Key>
<Property Name="AccountRemarkId" Type="int" Nullable="false" StoreGeneratedPattern="Identity"/>
<Property Name="AccountId" Type="int" Nullable="false"/>
<Property Name="RemarkTypeId" Type="int" Nullable="false"/>
<Property Name="RemarkEnteredAt" Type="datetime" Nullable="false"/>
<Property Name="EnteredBy" Type="nvarchar" Nullable="false" MaxLength="100"/>
<Property Name="Remark" Type="nvarchar" Nullable="false" MaxLength="300"/>
<Property Name="LastEditedBy" Type="nvarchar" Nullable="false" MaxLength="100"/>
</EntityType>
</Schema>
答案 1 :(得分:1)
使用此模板:
<xsl:template match="def:EntityType/def:Property[@Type = 'nvarchar(max)']">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="Type">nvarchar</xsl:attribute>
<xsl:attribute name="MaxLength">300</xsl:attribute>
</xsl:copy>
</xsl:template>