Изменить или удалить атрибут - PullRequest
1 голос
/ 07 августа 2011

У меня есть 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 ]

1 голос
/ 07 августа 2011

Используйте этот шаблон:

<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>
1 голос
/ 07 августа 2011

Проблема в этом коде :

    <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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...