2013-02-27 75 views
0

我想读取使用LINQ的xml文件中的“查询”元素值(它定义为CDATA),但是,当我运行应用程序时,以下值:使用LINQ从xml读取CDATA不返回预期的结果

System.Linq.Enumerable + WhereSelectEnumerableIterator`2 [System.Xml.Linq.XElement,System.String]

我很困惑,我很想念获得CDATA值。

XML文档看起来是这样的:

<?xml version="1.0" encoding="utf-8" ?> 
<dbprocedurestruct> 
    <variables id="vars"> 
    <variable id="ooid"> 
     <name>OrigOrgID</name> 
     <pseudo>Original Organization ID</pseudo> 
     <type>System.Int32</type> 
     <visible>true</visible> 
    </variable> 
    <variable id="noid"> 
     <name>NewOrgID</name> 
     <pseudo>New Organization(s) ID</pseudo> 
     <type>System.Int32</type> 
     <visible>true</visible> 
    </variable> 
    <variable id="nssid"> 
     <name>NewSysSubID</name> 
     <pseudo>New System Subscription ID</pseudo> 
     <type>System.Int32</type> 
     <visible>false</visible> 
    </variable> 
    </variables> 
    <scripts> 
    <script name="createscript"> 
     <query> 
     <![CDATA[ 
     SELECT 
     SystemSubscriptionID, 
     'INSERT INTO dbo.Subscriptions 
     (
     SubscriptionID, 
     SystemSubscriptionTierID, 
     IsCustomized, 
     SubscriptionPrice, 
     DownloadPrice, 
     PlansPrice, 
     SpecsPrice, 
     SubscriptionStartDate, 
     SubscriptionDuration, 
     AutoRenewSubscription, 
     IsActive, 
     SubscriptionStatus, 
     CreatedBy, 
     CreatedOn, 
     LastEditBy, 
     LastEditOn) 
     VALUES (' + 
     CAST(SubscriptionID AS VARCHAR(50)) + ',' + 
     CAST(SystemSubscriptionTierID AS VARCHAR(50)) + ',' + 
     CAST(IsCustomized AS VARCHAR(50)) + ',' + 
     CAST(SubscriptionPrice AS VARCHAR(50)) + ',' + 
     CAST(DownloadPrice AS VARCHAR(50)) + ',' + 
     CAST(PlansPrice AS VARCHAR(50)) + ',' + 
     CAST(SpecsPrice AS VARCHAR(50)) + ',''' + 
     CAST(GetDate() AS VARCHAR(50)) + ''',' + 
     CAST(SubscriptionDuration AS VARCHAR(50)) + ',' + 
     CAST(AutoRenewSubscription AS VARCHAR(50)) + ',' + 
     CAST(IsActive AS VARCHAR(50)) + ',' + 
     CAST(SubscriptionStatus AS VARCHAR(50)) + ', 2, ''' + 
     CAST(GetDate() AS VARCHAR(50)) + ''', 2, ''' + 
     CAST(GetDate() AS VARCHAR(50)) + ''') ' 
     FROM Subscriptions WHERE SystemSubscriptionID IN 
     (SELECT SystemSubscriptionID FROM SubscriptionMappings WHERE ReferenceID = {0}); 
     SELECT IDENT_CURRENT('Subscriptions') 
     ]]> 
     </query> 
    </script> 
    <script name="mappingscript"> 
     <query> 
     <![CDATA[ 
     INSERT INTO SubscriptionMappings 
     (SystemSubscriptionID, 
     ReferenceID, 
     SubscriptionTypeID, 
     SystemId, 
     IsActive, 
     CreatedBy) 
     SELECT 
     {0}, 
     {1}, 
     CAST(SubscriptionTypeID AS VARCHAR(50)), 
     2, 
     CAST(IsActive AS VARCHAR(50)), 
     2 FROM SubscriptionMappings 
     WHERE ReferenceID = {2} 
     AND 
     SystemSubscriptionID = {3} 
     ]]> 
     </query> 
    </script> 
    </scripts> 
</dbprocedurestruct> 

这里是我的代码片段读取XML文件:

SQLConnectivity _sc = new SQLConnectivity(); 
    DataTable dt = new DataTable(); 
    string xmlitem = (from scripts in xfile.Descendants("scripts") where scripts.Element("script").Value == "createscript" select scripts.Element("script").Element("query").Value).ToString(); 
    //String tempquery = xmlitem.Elements("query").ToString(); 
    String finalquery = String.Format(xmlitem, _ooid); 

    _sc.RunExecuteSQL(finalquery, ref dt); 
    return dt; 

回答

3

查询的结果是一个IEnumerable实例。如果你想要一个字符串结果,那么你需要使用FirstOrDefaultSingleOrDefault。另外,在搜索指定的“createscript”元素时,您需要使用“name”属性。

var sql = (from scripts in xfile.Root.Elements("scripts") 
      from script in scripts.Elements("script") 
      let name = script.Attribute("name") 
      where name != null && name.Value == "createscript" 
      from query in script.Elements("query") 
      select query.Value).FirstOrDefault(); 

编辑:开头和结尾的回车和缩进可以从与string.TrimRegex.Replace的组合的SQL被剥离。

var cleanSql = Regex.Replace(sql.Trim(), @"^\s+", "", RegexOptions.Multiline); 
+0

谢谢Nathan,那个工作很漂亮。我只需要弄清楚如何摆脱\ n角色。 – mattgcon 2013-02-27 05:46:29

+0

不用担心,我添加了一个清理SQL的建议,并进一步改进了LINQ查询。 – 2013-02-27 06:37:12