Visual Basic 中的 XPath
XPath in Visual Basic
我在 Visual Basic 中的 "SelectSingleNode" 函数有问题。
我有以下 XML 文件:
<sistema versao="1.02" xmlns="http://www.portalfiscal.inf.br/nfe">
<det>
<prod>
<cProd>000085</cProd>
<xProd>MARTELO</xProd>
<NCM>73170090</NCM>
<uCom>UN</uCom>
<vUnCom>7.0000</vUnCom>
</prod>
<imposto>
<ICMS>
<orig>0</orig>
<CST>500</CST>
</ICMS>
</imposto>
</det>
</sistema>
我需要节点 "cProd" 中的值。在这种情况下,“000085”。
我尝试了以下代码:
Public Sub importacao()
Dim arquivos = CheckedListBox1.CheckedItems
Dim total = arquivos.Count
Dim nome_produto As String
For i As Integer = 0 To total - 1
Dim xml As New XmlDocument
xml.Load(arquivos.Item(i))
nome_produto = xml.ChildNodes(0).ChildNodes(0).ChildNodes(0).SelectSingleNode("cProd").InnerText
Next
End Sub
在 "arquivos" 中是一个包含 XML 个文件路径的 CheckBoxList。
returns 错误 "Object reference not set to an instance of an object." 因为“SelectSingleNode("cProd")”返回空值。
我想我放置的 XPath 不正确。有人可以帮助我吗?
谢谢你,对不起我的英语。
编辑:
成功了,我使用了一个函数来删除命名空间(来源:http://rprateek.blogspot.com.br/2011/01/how-to-remove-xmlns-namespace-from-xml.html)。然后我可以使用以下内容:xml.ChildNodes(0).SelectSingleNode("//cProd").InnerText
还有一件事。如果标记 "cProd"(或另一个标记)在文件中不存在,那么处理可能导致的错误的最实用方法是什么?例如,在一些文件中,不会有标签 "NCM"。也许我可以用 "GetElementsByTagName()"?
验证标签是否存在
谢谢大家
如评论中所述,您不需要希望通过节点到达您想要的节点;你可以设置整个 XPath 来寻找你想要的节点。
不过,您的 XML 还是有点 问题 :它有一个没有前缀的命名空间:
<sistema versao="1.02" xmlns="http://www.portalfiscal.inf.br/nfe">
这对 XPath 查询造成了一些影响,因为所有节点都有默认的命名空间前缀 "cannot be seen",但它仍然存在。
您有三个选择:
1.- 从 XML...
中删除命名空间
<sistema versao="1.02">
<det>
<prod>
<cProd>000085</cProd>
<xProd>MARTELO</xProd>
<NCM>73170090</NCM>
<uCom>UN</uCom>
<vUnCom>7.0000</vUnCom>
</prod>
<imposto>
<ICMS>
<orig>0</orig>
<CST>500</CST>
</ICMS>
</imposto>
</det>
</sistema>
... 并使用
xml.ChildNodes(0).SelectSingleNode("//cProd").InnerText
或
xml.ChildNodes(0).SelectSingleNode("/sistema/det/prod/cProd").InnerText
2.- 指定一个前缀(ns
是一个例子,你可以随意命名)...
<ns:sistema versao="1.02" xmlns:ns="http://www.portalfiscal.inf.br/nfe">
<ns:det>
<ns:prod>
<ns:cProd>000085</ns:cProd>
<ns:xProd>MARTELO</ns:xProd>
<ns:NCM>73170090</ns:NCM>
<ns:uCom>UN</ns:uCom>
<ns:vUnCom>7.0000</ns:vUnCom>
</ns:prod>
<ns:imposto>
<ns:ICMS>
<ns:orig>0</ns:orig>
<ns:CST>500</ns:CST>
</ns:ICMS>
</ns:imposto>
</ns:det>
</ns:sistema>
...使用 XmlNameSpaceManager
...
Dim manager as New XmlNameSpaceManager(xml.NameTable)
... 并使用
xml.ChildNodes(0).SelectSingleNode("//ns:cProd", manager).InnerText
或
xml.ChildNodes(0).SelectSingleNode("/ns:sistema/ns:det/ns:prod/ns:cProd", manager).InnerText
3.- 保持 XML 不变,并使用
xml.ChildNodes(0).SelectSingleNode("//*[name()='cProd']").InnerText
或者这个小怪物
xml.ChildNodes(0).SelectSingleNode("/*[name()='sistema']/*[name()='det']/*[name()='prod']/*[name()='cProd']").InnerText
/*
让您忽略命名空间。
This question or this one 可能会帮助您更好地理解问题。
我在 Visual Basic 中的 "SelectSingleNode" 函数有问题。
我有以下 XML 文件:
<sistema versao="1.02" xmlns="http://www.portalfiscal.inf.br/nfe">
<det>
<prod>
<cProd>000085</cProd>
<xProd>MARTELO</xProd>
<NCM>73170090</NCM>
<uCom>UN</uCom>
<vUnCom>7.0000</vUnCom>
</prod>
<imposto>
<ICMS>
<orig>0</orig>
<CST>500</CST>
</ICMS>
</imposto>
</det>
</sistema>
我需要节点 "cProd" 中的值。在这种情况下,“000085”。
我尝试了以下代码:
Public Sub importacao()
Dim arquivos = CheckedListBox1.CheckedItems
Dim total = arquivos.Count
Dim nome_produto As String
For i As Integer = 0 To total - 1
Dim xml As New XmlDocument
xml.Load(arquivos.Item(i))
nome_produto = xml.ChildNodes(0).ChildNodes(0).ChildNodes(0).SelectSingleNode("cProd").InnerText
Next
End Sub
在 "arquivos" 中是一个包含 XML 个文件路径的 CheckBoxList。
returns 错误 "Object reference not set to an instance of an object." 因为“SelectSingleNode("cProd")”返回空值。
我想我放置的 XPath 不正确。有人可以帮助我吗?
谢谢你,对不起我的英语。
编辑:
成功了,我使用了一个函数来删除命名空间(来源:http://rprateek.blogspot.com.br/2011/01/how-to-remove-xmlns-namespace-from-xml.html)。然后我可以使用以下内容:xml.ChildNodes(0).SelectSingleNode("//cProd").InnerText
还有一件事。如果标记 "cProd"(或另一个标记)在文件中不存在,那么处理可能导致的错误的最实用方法是什么?例如,在一些文件中,不会有标签 "NCM"。也许我可以用 "GetElementsByTagName()"?
验证标签是否存在谢谢大家
如评论中所述,您不需要希望通过节点到达您想要的节点;你可以设置整个 XPath 来寻找你想要的节点。
不过,您的 XML 还是有点 问题 :它有一个没有前缀的命名空间:
<sistema versao="1.02" xmlns="http://www.portalfiscal.inf.br/nfe">
这对 XPath 查询造成了一些影响,因为所有节点都有默认的命名空间前缀 "cannot be seen",但它仍然存在。
您有三个选择:
1.- 从 XML...
中删除命名空间<sistema versao="1.02">
<det>
<prod>
<cProd>000085</cProd>
<xProd>MARTELO</xProd>
<NCM>73170090</NCM>
<uCom>UN</uCom>
<vUnCom>7.0000</vUnCom>
</prod>
<imposto>
<ICMS>
<orig>0</orig>
<CST>500</CST>
</ICMS>
</imposto>
</det>
</sistema>
... 并使用
xml.ChildNodes(0).SelectSingleNode("//cProd").InnerText
或
xml.ChildNodes(0).SelectSingleNode("/sistema/det/prod/cProd").InnerText
2.- 指定一个前缀(ns
是一个例子,你可以随意命名)...
<ns:sistema versao="1.02" xmlns:ns="http://www.portalfiscal.inf.br/nfe">
<ns:det>
<ns:prod>
<ns:cProd>000085</ns:cProd>
<ns:xProd>MARTELO</ns:xProd>
<ns:NCM>73170090</ns:NCM>
<ns:uCom>UN</ns:uCom>
<ns:vUnCom>7.0000</ns:vUnCom>
</ns:prod>
<ns:imposto>
<ns:ICMS>
<ns:orig>0</ns:orig>
<ns:CST>500</ns:CST>
</ns:ICMS>
</ns:imposto>
</ns:det>
</ns:sistema>
...使用 XmlNameSpaceManager
...
Dim manager as New XmlNameSpaceManager(xml.NameTable)
... 并使用
xml.ChildNodes(0).SelectSingleNode("//ns:cProd", manager).InnerText
或
xml.ChildNodes(0).SelectSingleNode("/ns:sistema/ns:det/ns:prod/ns:cProd", manager).InnerText
3.- 保持 XML 不变,并使用
xml.ChildNodes(0).SelectSingleNode("//*[name()='cProd']").InnerText
或者这个小怪物
xml.ChildNodes(0).SelectSingleNode("/*[name()='sistema']/*[name()='det']/*[name()='prod']/*[name()='cProd']").InnerText
/*
让您忽略命名空间。
This question or this one 可能会帮助您更好地理解问题。