2013-05-10 75 views
2

串我曾经在一个文件中的以下XML(简体):解析与VB.Net复杂的XML:元素注入取决于命名空间

<?xml version="1.0" encoding="ISO-8859-1"?> 
<XCer xmlns="http://x.y.z" xmlns:xsi="http://www.x.y.z" xsi:schemaLocation="http://www.x.y.z" track_id="559" mp_id="398" sub_id="569"> 
<capability xsi:type="XCracT"> 
<type>rec</type> 
<sub_type>pc</sub_type> 
<action>reco</action> 
</capability> 

<final_result OD="DGS=1.6" creator="Creator1" version="1.11" xsi:type="XCarT"> 
<code>300000000</code> 
<code_cnf>0.7454</code_cnf> 
<code_attr>seq</code_attr> 
<status_attr>fdos</status_attr> 
<text>this text</text> 
<standardized_text>other text</standardized_text> 
<region> 
    <type>add</type> 
    <symbology>machine</symbology> 
</region> 
</final_result> 

<final_result OD="DGS=1.7" creator="Creator2" version="1.11" xsi:type="XCarT"> 
<code>3040280100015</code> 
<code_cnf>0.7454</code_cnf> 
<code_attr>seq</code_attr> 
<status_attr>fdos</status_attr> 
<text>this text</text> 
<standardized_text>other text</standardized_text> 
<region> 
    <type>add</type> 
    <symbology>machine</symbology> 
</region> 
    <polygon> 
    <dot x="849" y="1600"/> 
    <dot x="823" y="1600"/> 
    <dot x="819" y="1166"/> 
    <dot x="845" y="1166"/> 
    </polygon> 
</final_result> 
</XCer> 

在一个非常基本的水平,我想创建3个变量:创造者,代码,mp_id,并填写最终结果OD =“DGS = 1.6”部分的细节,即'Creator1','300000000','398'(来自第一个XCer元素)和'本文',但我的XML技能是尽管在过去的几天里尝试了几个速成课程,但索雷利仍然缺乏。

我已经试过了基本

Using reader As XmlReader = XmlReader.Create("C:\filename.xml") 
while reader.Read() 
if reader.IsStartElement() Then 
If reader.Name = "code" Then 
code = reader.ReadElementContentAsString() 

这让我的代码,但我不能行
final_result OD="DGS=1.6" creator="Creator1" version="1.11" xsi:type="XCarT">

中得到任何的元素,我不能限制我想要的码元该子树不会覆盖前面的代码。

回答

2

这里有一个如何使用XPath做一个简单的例子:

Dim doc As New XmlDocument() 
doc.Load("Test.xml") 
Dim namespaceManager As New XmlNamespaceManager(doc.NameTable) 
namespaceManager.AddNamespace("x", "http://x.y.z") 
Dim mp_id As String = doc.SelectSingleNode("/x:XCer[1]/@mp_id", namespaceManager).InnerText 
Dim creator As String = doc.SelectSingleNode("/x:XCer[1]/x:final_result[@OD='DGS=1.6']/@creator", namespaceManager).InnerText 
Dim code As String = doc.SelectSingleNode("/x:XCer[1]/x:final_result[@OD='DGS=1.6']/x:code", namespaceManager).InnerText 

注意,我需要指定命名空间,因为所有的元素有http://x.y.z默认命名空间。为了我的目的,我给名称空间添加了前缀x,但您可以将其命名为任何您想要的名称。

XPath是用于查询XML文档的标准语言。有些人更喜欢微软专有的LINQ技术,但由于XPath是其他语言,工具和技术所使用的技术,因此花时间学习它是非常值得的。 SelectSingleNodeSelectNodes方法允许您使用XPath查找匹配的节点。

第一XPath,它选择mp_id,看起来像这样:

/X:XCer [1]/@ MP_ID

  • / - 开始在文档的根(在x命名空间中)
  • [1] - 选择仅第一XCer元件
  • / - 寻找第一XCer元件的后继节点
  • @mp_id - 选择mp_id属性(其是第一XCer元件的后继节点)

下一个选择creator属性的XPath如下所示:

/x:XCe R [1]/X:final_result [@ OD ='DGS = 1。6' ]/@创建者

这一个启动一样的最后一个,但不是选择XCer元素的属性,它选择一个final_result子元素。 [@OD='DGS=1.6']是一个条件子句。您可以阅读它,如“选择final_result元素,其OD属性等于DGS=1.6”。

+0

这是梦幻般的史蒂芬,我已经放弃了一些已放弃的NameSpaceManager尝试,因为我无法正确定义SelectSingleNode的第一部分。是否有关于如何生成字符串“/x:XCer[1]/x:final_result[@OD='DGS=1.6']/@creator”的文档的好来源? – foreachin 2013-05-10 13:32:32

+0

不幸的是,我没有任何建议最好去学习XPath。我通过一些O'Reilly关于XSLT的书(它主要依赖于XPath)了解了它,但我相信有更好的书籍和站点可供学习XPath。我只需在Web上搜索XPath并查看您的兴趣。 – 2013-05-10 14:04:38

0

如果您不知道底层XML结构并尝试根据某个标签名称找到节点。注意:xml可能会根据搜索到的标签定义名称空间。在下面的示例中,我们正在搜索XML标记CashInAccountNumber但在实际的xml中它具有名称空间声明,如“bctr:CashInAccountNumber”。以下是XML结构:

<xfa:data xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"><bctr:BSAForm xmlns:bctr="http://www.fincen.gov/bsa/bctr/2011-06-01" xmlns:cc="http://www.fincen.gov/bsa/common-components/2009-01-01" xmlns:est="http://www.fincen.gov/bsa/efile-submission-types/2009-01-01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><bctr:PersonInformation><bctr:CashInAccountNumber><bctr:CashInAccountNumber /></bctr:CashInAccountNumber><bctr:CashOutAccountNumber><bctr:CashOutAccountNumber /></bctr:CashOutAccountNumber></bctr:PersonInformation><xfdf:field xmlns:xfdf="http://ns.adobe.com/xfdf/" xmlns:xfdfi="http://ns.adobe.com/xfdf-transition/" xfdfi:original="FSAPPLICATIONDATA_">n6835LaAwLhBAAA</xfdf:field><xfdf:field xmlns:xfdf="http://ns.adobe.com/xfdf/" xmlns:xfdfi="http://ns.adobe.com/xfdf-transition/" xfdfi:original="FSTARGETURL_">https://sdtmut1.fincen.treas.gov/AltSubmitServlet</xfdf:field></bctr:BSAForm><FSTEMPLATE_ /><FSFORMQUERY_>BCTR.pdf</FSFORMQUERY_><FSTRANSFORMATIONID_>PDFForm</FSTRANSFORMATIONID_><FSTARGETURL_>https://sdtmut1.fincen.treas.gov/AltSubmitServlet</FSTARGETURL_><FSAWR_>https://sdtmut1.fincen.treas.gov/</FSAWR_><FSWR_>https://sdtmut1.fincen.treas.gov/FormServer</FSWR_><FSCRURI_>/opt/weblogic/user_projects/domains/BSADomain/applications/FinCEN1/forms</FSCRURI_><FSBASEURL_>https://sdtmut1.fincen.treas.gov/</FSBASEURL_></xfa:data> 

在这种情况下,尝试使用死者(“CashInAccountNumber”)方法得到的值,如果仍然没有找到,那么使用下面的代码片段搜索:

 Try 
     Dim fs As New FileStream("Your XML File Path", FileMode.Open, FileAccess.Read) 

     Dim objDocument As New XPathDocument(fs) 
     Dim objNavigator As XPathNavigator = objDocument.CreateNavigator() 
     Dim objNodeIterator As XPathNodeIterator = objNavigator.[Select]("//namespace::*[not(. = ../../namespace::*)]") 
     While objNodeIterator.MoveNext() 
      Dim sKey As String = objNodeIterator.Current.LocalName 
      If Not dictNameSpace.ContainsKey(sKey) Then 
       dictNameSpace.Add(objNodeIterator.Current.LocalName, objNodeIterator.Current.Value) 
      End If 
     End While 

     fs = New FileStream("Your XML File Path", FileMode.Open, FileAccess.Read) 
     Dim xmlr As XDocument = XDocument.Load(fs) 

     For Each kvp As KeyValuePair(Of String, String) In dictNameSpace 
      Dim ns As XNamespace = kvp.Value 
      For Each xEle As XElement In xmlr.Descendants(ns + "CashInAccountNumber") 
       Console.WriteLine("Found Tag:" + xEle.Name.LocalName) 
      Next xEle 
     Next 

    Catch ex As Exception 
     Console.WriteLine(ex.Message) 
    End Try