开发者

Change or Remove an Attribute

I have an XML document that looks like this:

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

I am trying to transform it with XSLT so that the new document is identical, with just one line of difference. The line to be changed is this:

    <Property Name="Remark" Type="nvarchar(max)" Nullable="false" /开发者_JAVA技巧>

It should be transformed into this:

    <Property Name="Remark" Type="nvarchar" Nullable="false" MaxLength="300" />

My XSLT transform so far looks like this:

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

I'm stepping through the transform with Visual Studio 2010 debugging, and I see that it correctly activates the [@Type='nvarchar(max)']/@* template. The only problem is that the xsl:when test="@Type='nvarchar(max)'" never tests as true. Of course this is bizarre, because if the template itself matched, then this identical condition should match as well.

But because the when test strangely doesn't become true, my target doesn't get transformed at all, and I simply end up with an exact copy of the original document. If I change the when clause to xsl:when test="1=1" then it finally tests as true, which demonstrates that overall the transform is correct. But this still begs the question: why is the proper expression never becoming true?

I'm just simply unable to figure why the proper test expression never becomes true. Ideas?


Use this 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>


The problem is in this code:

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

This line: <xsl:when test="@Type='nvarchar(max)'">

tests if the current (matched) node has an attribute named Type that has a specific value. However, only elements can have attributes and attributes never have attributes themselves. Therefore the comparison is always false().

One possible solution:

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

when applied on the provided XML document:

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

the wanted, correct result is produced:

<?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>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜