使用VB.Net将复杂的xml解析:根据命名空间将元素转换为字符串

时间:2013-05-10 12:10:02

标签: xml vb.net xml-parsing

我在文件中有以下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个变量:creator,code,mp_id,并用最终结果OD =“DGS = 1.6”部分的细节填充它们,即'Creator1','300000000','398' (来自第一个XCer元素)和'this text'但是我的xml技能在soreley缺乏,尽管在过去几天尝试了几个速成课程。

我尝试了基本的

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 个答案:

答案 0 :(得分: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查找匹配的节点。

选择mp_id的第一个XPath如下所示:

  

/ X:XCer [1] / @ MP_ID

  • / - 从文档的根目录开始
  • x:XCer - 查找名为XCer的元素(在x命名空间中)
  • [1] - 仅选择第一个XCer元素
  • / - 查找第一个XCer元素的后代节点
  • @mp_id - 选择mp_id属性(第一个XCer元素的后代节点)

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

  

/ X:XCer [1] / X:final_result [@ OD = 'DGS = 1.6'] / @创建者

这一个与最后一个相同,但不是选择XCer元素的属性,而是选择final_result子元素。 [@OD='DGS=1.6']是条件子句。您可以将其读作“选择final_result元素,其OD属性等于DGS=1.6”。

答案 1 :(得分:0)

如果您不了解基础XML结构并尝试根据某些标记名称查找节点。注意:xml可能针对搜索的标记定义了名称空间。在下面的示例中,我们搜索XML标记 CashInAccountNumber ,但在实际的xml中,它具有名称空间声明,如&#34; bctr:CashInAccountNumber&#34; 。以下是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>

在这种情况下,尝试使用死者(&#34; CashInAccountNumber&#34;)方法获取价值,如果仍未找到,则使用下面的代码片段进行搜索:

        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