LINQ to XML Axis属性在使用其他属性选择元素时返回属性

时间:2012-10-03 21:01:42

标签: xml vb.net linq

代码块四(下面)给我一个错误,我在修复方面感到茫然...

这是我正在使用的XML Schema:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

<!DOCTYPE ctqcfg SYSTEM "cache.dtd">

<cache version="1.0">
    <configuration name="Test">
        <cacheControl>
            <cache name="Customer" mode="off"/>
            <cache name="Vendor" mode="off"/>
            <cache name="Agency" mode="off"/>
            <cache name="Partner" mode="off"/>
        </cacheControl>
    </configuration>

    <configuration name="Production">
        <cacheControl>
            <cache name="Customer" mode="preload"/>
            <cache name="Vendor" mode="dynamic"/>
            <cache name="Agency" mode="dynamic"/>
            <cache name="Partner" mode="dynamic"/>
        </cacheControl>
    </configuration>
</cache>

加载XML文件

Private XElement As XElement = Nothing

Public Sub Load()
    XElement = XElement.Load(ConfigurationResource)
End Sub

当用户选择要编辑的配置时,将保留对所选配置元素的根的引用

Private ConfigurationRoot As System.Collections.Generic.IEnumerable(Of System.Xml.Linq.XElement)

Private ConfigurationName_ As String

Public Property ConfigurationName() As String
    Get
        Return ConfigurationName_
    End Get
    Set(ByVal Value As String)
        ConfigurationName_ = Value
        ConfigurationRoot = From Configuration In XElement.<configuration> Where Configuration.@name = Value
    End Set
End Property

尝试检索与缓存名称相对应的缓存模式(在本例中为Customer)

Public Property CustomerCache() As String
    Get
        Try
            Return From Cache In ConfigurationRoot.<cacheControl>.<cache> Where Cache.@name = "Customer" Select Cache.@mode
        Catch Exception As Exception
            Return Nothing
        End Try
    End Get
    Set(ByVal Value As String)
        'ToDo
    End Set
End Property

我收到以下错误

System.InvalidCastException was caught
Message=Unable to cast object of type 'WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.String]' to type 'System.String'.

这是我使用LINQ的第一天,我似乎对如何访问该属性有一个基本的误解 - 似乎查询返回了一个集合,我知道只有一个可能的值可以找到...

2 个答案:

答案 0 :(得分:1)

您需要.First().Single()

Return (From Cache In ConfigurationRoot.<cacheControl>.<cache> Where Cache.@name = "Customer" Select Cache.@mode).First()

答案 1 :(得分:0)

前三个代码块都实现了相同的结果,但访问属性内容的方法略有不同:

1。直接返回“encrypted”属性的第一个(也是唯一的)实例:

Return "true" = (From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>.@encrypted).Single

2。查询XElements集合,然后从第一个XElement方法中提取“encrypted”属性:

Dim Element As IEnumerable(Of XElement) = (From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single
Return "true" = Element(0).@encrypted

前面的例子轻轻地误导我们,因为.Single引用明确指出将会找到一个且只有一个 - 但实际上我们必须处理一个集合的结果(只有一个项目)。与方法1相比,它更加令人困惑,我们不必明确处理集合来检索属性值。

3A。查询集合中的第一个XElement然后拉出“加密”属性方法:

Dim Element As XElement = ((From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single)(0)
Return "true" = Element.@encrypted

最后一个例子通过引用集合中的第一个项目并将其存储在内部,努力处理必须处理集合(一个项目)以尽快检索集合中的项目的误导性部分。适当的类型,以便我们可以不再担心集合,而是处理我们真正感兴趣的对象(在本例中是一个XElement对象)。

3B。更改第一个XElement对象中的“encrypted”属性

Dim Element As XElement = ((From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single)(0)
If Value Then
    Element.@encrypted = "true"
Else
    Element.@encrypted = "false"
End If

使用三种查询方法有助于澄清我的心理模型,了解LINQ返回的内容。另外,我需要了解这里真正要修改“加密”属性...