我试图在Linq中理解XML并且我有这个文件XML:
<?xml version="1.0" encoding="utf-8"?>
<Headers xmlns="http://tempuri.org/GridLayerSchema.xsd">
<Header>
<Name>Layer0</Name>
<Fields FieldID="FieldID0" FieldName="FieldNameAll" FieldPosition="0" FieldPositionStart="0" FieldLenght="254" FieldEnable="true" />
</Header>
<Header>
<Name>Layer1</Name>
<Fields FieldID="FieldID0" FieldName="JetPosition" FieldPosition="0" FieldPositionStart="0" FieldLenght="14" FieldEnable="true" />
<Fields FieldID="FieldID1" FieldName="Owner" FieldPosition="1" FieldPositionStart="14" FieldLenght="14" FieldEnable="true" />
<Fields FieldID="FieldID2" FieldName="Item" FieldPosition="2" FieldPositionStart="28" FieldLenght="3" FieldEnable="true" />
</Header>
</Headers>
我将尝试使用linq查询获取所有元素来制作VB.net类,有些想法是这样的:
Class Field:
Public Class Field
Public Property FieldID1 As String
Public Property FieldName As String
Public Property FieldPosition As Integer
Public Property FieldPositionStart As Integer
Public Property FieldLenght As Integer
Public Property FieldEnable As Boolean
End Class
然后是Header类:
Public Class Header : Inherits Field
Public Property Name As String
End Class
在这一个中,我是一个制作Headers系列的功能:
Public Shared Function HeadersLoader() As Headers
Dim HeadersCollection As New Headers
Dim ns As XNamespace = "http://tempuri.org/GridLayerSchema.xsd"
Dim xdoc As XDocument = XDocument.Load(My.Application.Info.DirectoryPath & "\Layers\Headers.xml")
Dim HeadersQuery = From Header In xdoc.Root.Elements(ns + "Header")
Select Header
For Each e In HeadersQuery
Dim _mHeader As New Header
With _mHeader
.Name = e.Value.ToString
End With
HeadersCollection.Add(_mHeader)
Next
Return HeadersCollection
End Function
现在我有两个问题:
为什么我在Value属性中有Header的名称,而不在Name属性中(在name属性中我有所有的名称空间和标题标记,但不是名称:{http://tempuri.org/GridLayerSchema.xsd} Header)
如何读取当前标题的所有字段?我需要嵌套查询吗?我想,通过我的查询,找到所有但似乎不是这样,我只能读取第一个节点。
答案 0 :(得分:1)
您Value
上的XElement
属性将连接元素中的所有文本节点,包括后代中的文本节点,这让您感到困惑。 发生以获取Name
子元素的文本值,因为这是您使用任何文本获得的唯一元素。最好写一下:
With _mHeader
.Name = e.Element(ns + "Name").Value
通过这种方式,您明确要求<Name>
子元素中的文字。
现在你的课堂设计有点乱,因为你说的是标题是一个字段,而不是 一个字段列表。我想你应该有类似的东西:
Public Class Header
Public Property Name As String
Public Property Fields As List(Of Field)
End Class
(可能有一些初始化)。然后,我将更改您的LINQ查询,以在Header
子句中创建Select
的实例。我不打算尝试VB,但在C#中我会有类似的东西:
var headers = xdoc.Root.Elements(ns + "Header")
.Select(header => new Header
{
Name = header.Element("Name").Value,
Fields = header.Elements("Fields")
.Select(field => new Field
{
FieldID1 = field.Element("FieldID)".Value,
// etc
})
.ToList();
});
您可能希望将静态FromXElement
方法添加到Header
和Field
(其中Header.FromXElement
将使用Field.FromXElement
)以使这一切变得更加简单。
答案 1 :(得分:0)
Sub Main()
Dim xml = <?xml version="1.0" encoding="utf-8"?>
<Headers xmlns="http://tempuri.org/GridLayerSchema.xsd">
<Header>
<Name>Layer0</Name>
<Fields FieldID="FieldID0" FieldName="FieldNameAll" FieldPosition="0" FieldPositionStart="0" FieldLenght="254" FieldEnable="true"/>
</Header>
<Header>
<Name>Layer1</Name>
<Fields FieldID="FieldID0" FieldName="JetPosition" FieldPosition="0" FieldPositionStart="0" FieldLenght="14" FieldEnable="true"/>
<Fields FieldID="FieldID1" FieldName="Owner" FieldPosition="1" FieldPositionStart="14" FieldLenght="14" FieldEnable="true"/>
<Fields FieldID="FieldID2" FieldName="Item" FieldPosition="2" FieldPositionStart="28" FieldLenght="3" FieldEnable="true"/>
</Header>
</Headers>
Dim ns As XNamespace = "http://tempuri.org/GridLayerSchema.xsd"
Dim query = (From elmHeader In xml.Root.Elements(ns + "Header")
Select New Header With {
.Name = CStr(elmHeader.Element(ns + "Name")),
.Fields = (From elmField In elmHeader.Elements(ns + "Fields")
Select New Field With {
.FieldID1 = CStr(elmField.Attribute("FieldID")),
.FieldName = CStr(elmField.Attribute("FieldName")),
.FieldPosition = CInt(elmField.Attribute("FieldPosition")),
.FieldPositionStart = CInt(elmField.Attribute("FieldPositionStart")),
.FieldLenght = CInt(elmField.Attribute("FieldLenght")),
.FieldEnable = CBool(elmField.Attribute("FieldEnable"))
}).ToList()
}).ToList()
End Sub
Public Class Field
Public Property FieldID1 As String
Public Property FieldName As String
Public Property FieldPosition As Integer
Public Property FieldPositionStart As Integer
Public Property FieldLenght As Integer
Public Property FieldEnable As Boolean
End Class
Public Class Header : Inherits Field 'I think you can drop this inherits but that's up to you
Public Property Name As String
Public Property Fields As IEnumerable(Of Field)
End Class
...顺便说一句,如果你在文件的顶部添加一个Imports,你可以用XML文字更多地清理查询。
Imports <xmlns:ns="http://tempuri.org/GridLayerSchema.xsd">
...
Dim query = From elmHeader In xml.Root.<ns:Header>
Select New Header With {
.Name = elmHeader.<ns:Name>.First(),
.Fields = From elmField In elmHeader.<ns:Fields>
Select New Field With {
.FieldID1 = elmField.@FieldID,
.FieldName = elmField.@FieldName,
.FieldPosition = elmField.@FieldPosition,
.FieldPositionStart = elmField.@FieldPositionStart,
.FieldLenght = elmField.@FieldLenght,
.FieldEnable = elmField.@FieldEnable
}
}