使用 LINQ 解析根元素中带有命名空间的 XML 文档
Using LINQ to Parse XML Document with Namespace in Root Element
我有以下 XML 个名为 Example.xml 的文件。请注意根元素 Message 中的命名空间规范 (xmlns),因为下面的问题与此相关。
<?xml version="1.0" encoding="utf-8" ?>
<Message xmlns="http://www.myurl.com/Product" version="010" release="006">
<Header>
<To Qualifier="P" />
<From Qualifier="D" />
<MessageID>f244251a8c6c4070</MessageID>
<SentTime>2018-03-21T22:01:16.70Z</SentTime>
</Header>
<Body>
<Product>
<Description>
<Identification>
<ID1>1871598417</ID1>
<ID2>BE9432042-1234</ID2>
</Identification>
<Type>
<Name>Home Widget</Name>
<Category>Residential</Category>
</Type>
</Description>
</Product>
</Body>
</Message>
我使用 LINQ
将以下函数写入 return 字符串
Public Function GetProductDetail() As String
Dim xDoc As XDocument = Nothing
Dim returnValue As String = ""
Using xr As XmlReader = XmlReader.Create("C:\Automation\Example.xml")
xDoc = XDocument.Load(xr)
Dim query = From t In xDoc.Descendants("Body")
Select New With {Key _
.ID1 = t.Element("Product").Element("Description").Element("Identification").Element("ID1").Value,
.ID2 = t.Element("Product").Element("Description").Element("Identification").Element("ID2").Value,
.Name = t.Element("Product").Element("Description").Element("Type").Element("Name").Value}
For Each item In query
returnValue = $"ID1: {item.ID1} | ID2: {item.ID2} | Name: {item.Name}"
Next
End Using
Return returnValue
End Function
我遇到的问题是上述 XML 文件的 return 值是空白。
当我将根元素更改为仅如下:
<Message>
(即删除所有内容,包括 xmlns=....)我得到正确的 return 值
return值 = ID1:1871598417 | ID2:BE9432042-1234 |名称:主页小部件
我有以下问题:
当 xmlns 是根元素的一部分时,我需要在我的代码或 XPath 表达式中添加什么。
有时 XML 文件可能不包含 ID2 元素。如果该元素不存在或者这甚至可以通过 LINQ 实现,我该如何检查 LINQ 查询。
如果这不适合使用 LINQ,请有人提供有关如何完成此操作的代码。
感谢大家的投入、时间和帮助。
谢谢
朱瑟
问题是您没有为命名空间命名。
例如:
<Message xmlns:name="http://www.myurl.com/Product" version="010" release="006">
.
如果您不为命名空间使用自定义名称,则必须使用整个命名空间作为标识符。
这是没有自定义名称的主体名称
{{http://www.myurl.com/Product}Body}
这是自定义名称 {Body}
(现在你会问为什么元素主体的名称没有前面的 {name:Body}
发生这种情况是因为它没有任何命名含义)
您可以使用 Null 条件运算符。
例如:t.Element("Product").Element("Description").Element("Identification").Element("ID1")?.Value
尽管这不是答案 LINQ 基本上是一种执行复杂 foreach 的方法。所以我唯一会做的可能是使用 XPath 而不是链接元素,这些元素可能在特性中的任何一个都可能以 null 结束。
希望对您有所帮助。如果有任何问题,请随时提出,我会尽力解释。
谢谢,
编辑:
当您想使用命名空间查找 xml 节点时,您可以使用这种代码。 (如果我做错了什么,请原谅我,我是 C# Dev 而不是 Visual Basic)
Dim nameSpace As xDoc.Root.GetDefaultNamespace()?.NamespaceName
Dim body As xDoc.Descendants(XName.Get("Body", nameSpace))
Dim productXName As XName.Get("Product", nameSpace)
Dim descriptionXName As XName.Get("Description", nameSpace)
Dim identificationXName As XName.Get("Identification", nameSpace)
Dim id1XName As XName.Get("ID1", nameSpace)
Dim id2XName As XName.Get("ID2", nameSpace)
Dim typeXName As XName.Get("Type", nameSpace)
Dim nameXName As XName.Get("Name", nameSpace)
Dim query As From t In body
select New With {Key _
.ID1 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id1XName)?.Value,
.ID2 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id2XName)?.Value,
.Name = t.Element(productXName).Element(descriptionXName).Element(typeXName).Element(nameXName)?.Value}
' 更新工作 VB.Net 代码
Public Function GetProductDetail() As String
Dim xDoc As XDocument = Nothing
Dim returnValue As String = ""
Using xr As XmlReader = XmlReader.Create("C:\Automation\Example.xml")
xDoc = XDocument.Load(xr)
Dim xn = xDoc.Root.GetDefaultNamespace()?.NamespaceName
Dim body = xDoc.Descendants(XName.Get("Body", xn))
Dim productXName = XName.Get("Product", xn)
Dim descriptionXName = XName.Get("Description", xn)
Dim identificationXName = XName.Get("Identification", xn)
Dim id1XName = XName.Get("ID1", xn)
Dim id2XName = XName.Get("ID2", xn)
Dim typeXName = XName.Get("Type", xn)
Dim nameXName = XName.Get("Name", xn)
' Name1 May or Maynot exist in the XML file
Dim nameXName1 = XName.Get("Name1", xn)
' DT May or May not Exist in recived XML File
Dim query = From t In body
Select New With {Key _
.ID1 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id1XName)?.Value,
.ID2 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id2XName)?.Value,
.Name = t.Element(productXName).Element(descriptionXName).Element(typeXName).Element(nameXName)?.Value,
.DT = t.Element(productXName).Element(descriptionXName).Element(typeXName).Element(nameXName1)?.Value}
For Each item In query
returnValue = $"ID1: {item.ID1} | ID2: {item.ID2} | Name: {item.Name} | DT: {item.DT} "
Next
End Using
Return returnValue
End Function
我有以下 XML 个名为 Example.xml 的文件。请注意根元素 Message 中的命名空间规范 (xmlns),因为下面的问题与此相关。
<?xml version="1.0" encoding="utf-8" ?>
<Message xmlns="http://www.myurl.com/Product" version="010" release="006">
<Header>
<To Qualifier="P" />
<From Qualifier="D" />
<MessageID>f244251a8c6c4070</MessageID>
<SentTime>2018-03-21T22:01:16.70Z</SentTime>
</Header>
<Body>
<Product>
<Description>
<Identification>
<ID1>1871598417</ID1>
<ID2>BE9432042-1234</ID2>
</Identification>
<Type>
<Name>Home Widget</Name>
<Category>Residential</Category>
</Type>
</Description>
</Product>
</Body>
</Message>
我使用 LINQ
将以下函数写入 return 字符串Public Function GetProductDetail() As String
Dim xDoc As XDocument = Nothing
Dim returnValue As String = ""
Using xr As XmlReader = XmlReader.Create("C:\Automation\Example.xml")
xDoc = XDocument.Load(xr)
Dim query = From t In xDoc.Descendants("Body")
Select New With {Key _
.ID1 = t.Element("Product").Element("Description").Element("Identification").Element("ID1").Value,
.ID2 = t.Element("Product").Element("Description").Element("Identification").Element("ID2").Value,
.Name = t.Element("Product").Element("Description").Element("Type").Element("Name").Value}
For Each item In query
returnValue = $"ID1: {item.ID1} | ID2: {item.ID2} | Name: {item.Name}"
Next
End Using
Return returnValue
End Function
我遇到的问题是上述 XML 文件的 return 值是空白。
当我将根元素更改为仅如下:
<Message>
(即删除所有内容,包括 xmlns=....)我得到正确的 return 值
return值 = ID1:1871598417 | ID2:BE9432042-1234 |名称:主页小部件
我有以下问题:
当 xmlns 是根元素的一部分时,我需要在我的代码或 XPath 表达式中添加什么。
有时 XML 文件可能不包含 ID2 元素。如果该元素不存在或者这甚至可以通过 LINQ 实现,我该如何检查 LINQ 查询。
如果这不适合使用 LINQ,请有人提供有关如何完成此操作的代码。
感谢大家的投入、时间和帮助。
谢谢
朱瑟
问题是您没有为命名空间命名。 例如:
<Message xmlns:name="http://www.myurl.com/Product" version="010" release="006">
.如果您不为命名空间使用自定义名称,则必须使用整个命名空间作为标识符。
这是没有自定义名称的主体名称
{{http://www.myurl.com/Product}Body}
这是自定义名称{Body}
(现在你会问为什么元素主体的名称没有前面的{name:Body}
发生这种情况是因为它没有任何命名含义)您可以使用 Null 条件运算符。
例如:t.Element("Product").Element("Description").Element("Identification").Element("ID1")?.Value
尽管这不是答案 LINQ 基本上是一种执行复杂 foreach 的方法。所以我唯一会做的可能是使用 XPath 而不是链接元素,这些元素可能在特性中的任何一个都可能以 null 结束。
希望对您有所帮助。如果有任何问题,请随时提出,我会尽力解释。
谢谢,
编辑:
当您想使用命名空间查找 xml 节点时,您可以使用这种代码。 (如果我做错了什么,请原谅我,我是 C# Dev 而不是 Visual Basic)
Dim nameSpace As xDoc.Root.GetDefaultNamespace()?.NamespaceName
Dim body As xDoc.Descendants(XName.Get("Body", nameSpace))
Dim productXName As XName.Get("Product", nameSpace)
Dim descriptionXName As XName.Get("Description", nameSpace)
Dim identificationXName As XName.Get("Identification", nameSpace)
Dim id1XName As XName.Get("ID1", nameSpace)
Dim id2XName As XName.Get("ID2", nameSpace)
Dim typeXName As XName.Get("Type", nameSpace)
Dim nameXName As XName.Get("Name", nameSpace)
Dim query As From t In body
select New With {Key _
.ID1 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id1XName)?.Value,
.ID2 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id2XName)?.Value,
.Name = t.Element(productXName).Element(descriptionXName).Element(typeXName).Element(nameXName)?.Value}
' 更新工作 VB.Net 代码
Public Function GetProductDetail() As String
Dim xDoc As XDocument = Nothing
Dim returnValue As String = ""
Using xr As XmlReader = XmlReader.Create("C:\Automation\Example.xml")
xDoc = XDocument.Load(xr)
Dim xn = xDoc.Root.GetDefaultNamespace()?.NamespaceName
Dim body = xDoc.Descendants(XName.Get("Body", xn))
Dim productXName = XName.Get("Product", xn)
Dim descriptionXName = XName.Get("Description", xn)
Dim identificationXName = XName.Get("Identification", xn)
Dim id1XName = XName.Get("ID1", xn)
Dim id2XName = XName.Get("ID2", xn)
Dim typeXName = XName.Get("Type", xn)
Dim nameXName = XName.Get("Name", xn)
' Name1 May or Maynot exist in the XML file
Dim nameXName1 = XName.Get("Name1", xn)
' DT May or May not Exist in recived XML File
Dim query = From t In body
Select New With {Key _
.ID1 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id1XName)?.Value,
.ID2 = t.Element(productXName).Element(descriptionXName).Element(identificationXName).Element(id2XName)?.Value,
.Name = t.Element(productXName).Element(descriptionXName).Element(typeXName).Element(nameXName)?.Value,
.DT = t.Element(productXName).Element(descriptionXName).Element(typeXName).Element(nameXName1)?.Value}
For Each item In query
returnValue = $"ID1: {item.ID1} | ID2: {item.ID2} | Name: {item.Name} | DT: {item.DT} "
Next
End Using
Return returnValue
End Function