更改或删除属性

时间:2011-08-07 00:14:04

标签: xml visual-studio xslt xpath transform

我有一个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,这表明整体转换是正确的。但这仍然引出了一个问题:为什么正确的表达永远不会成为现实?

我只是无法弄清楚为什么正确的测试表达式永远不会成真。想法?

2 个答案:

答案 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>