2009-05-18 7 views
1

Un possible (travail) Solution:

Private Sub ReadXMLAttributes(ByVal oXML As String) 
    ReadXMLAttributes(oXML, "mso-infoPathSolution") 
End Sub 
Private Sub ReadXMLAttributes(ByVal oXML As String, ByVal oTagName As String) 
    Try 
     Dim XmlDoc As New Xml.XmlDocument 
     XmlDoc.LoadXml(oXML) 
     oFileInfo = New InfoPathDocument 
     Dim XmlNodes As Xml.XmlNodeList = XmlDoc.GetElementsByTagName(oTagName) 
     For Each xNode As Xml.XmlNode In XmlNodes 
      With xNode 
       oFileInfo.SolutionVersion = .Attributes(InfoPathSolution.solutionVersion).Value 
       oFileInfo.ProductVersion = .Attributes(InfoPathSolution.productVersion).Value 
       oFileInfo.PIVersion = .Attributes(InfoPathSolution.PIVersion).Value 
       oFileInfo.href = .Attributes(InfoPathSolution.href).Value 
       oFileInfo.name = .Attributes(InfoPathSolution.name).Value 
      End With 
     Next 
    Catch ex As Exception 
     MsgBox(ex.Message, MsgBoxStyle.OkOnly, "ReadXMLAttributes") 
    End Try 
End Sub 

Cela fonctionne, mais il faudra encore souffrir du problème ci-dessous si les attributs sont réorganisés. La seule façon que je puisse penser pour éviter ce problème est de coder en dur les noms d'attributs dans mon programme, et de le faire traiter l'entrée en faisant une boucle sur la balise analysée et en recherchant les balises désignées.Lecture des informations de balise XML en VB.NET

REMARQUE: InfoPathDocument est une classe personnalisée j'ai fait, il est rien de compliqué:

Public Class InfoPathDocument 
    Private _sVersion As String 
    Private _pVersion As String 
    Private _piVersion As String 
    Private _href As String 
    Private _name As String 
    Public Property SolutionVersion() As String 
     Get 
      Return _sVersion 
     End Get 
     Set(ByVal value As String) 
      _sVersion = value 
     End Set 
    End Property 
    Public Property ProductVersion() As String 
     Get 
      Return _pVersion 
     End Get 
     Set(ByVal value As String) 
      _pVersion = value 
     End Set 
    End Property 
    Public Property PIVersion() As String 
     Get 
      Return _piVersion 
     End Get 
     Set(ByVal value As String) 
      _piVersion = value 
     End Set 
    End Property 
    Public Property href() As String 
     Get 
      Return _href 
     End Get 
     Set(ByVal value As String) 
      If value.ToLower.StartsWith("file:///") Then 
       value = value.Substring(8) 
      End If 
      _href = Form1.PathToUNC(URLDecode(value)) 
     End Set 
    End Property 
    Public Property name() As String 
     Get 
      Return _name 
     End Get 
     Set(ByVal value As String) 
      _name = value 
     End Set 
    End Property 
    Sub New() 

    End Sub 
    Sub New(ByVal oSolutionVersion As String, ByVal oProductVersion As String, ByVal oPIVersion As String, ByVal oHref As String, ByVal oName As String) 
     SolutionVersion = oSolutionVersion 
     ProductVersion = oProductVersion 
     PIVersion = oPIVersion 
     href = oHref 
     name = oName 
    End Sub 
    Public Function URLDecode(ByVal StringToDecode As String) As String 
     Dim TempAns As String = String.Empty 
     Dim CurChr As Integer = 1 
     Dim oRet As String = String.Empty 
     Try 
      Do Until CurChr - 1 = Len(StringToDecode) 
       Select Case Mid(StringToDecode, CurChr, 1) 
        Case "+" 
         oRet &= " " 
        Case "%" 
         oRet &= Chr(Val("&h" & Mid(StringToDecode, CurChr + 1, 2))) 
         CurChr = CurChr + 2 
        Case Else 
         oRet &= Mid(StringToDecode, CurChr, 1) 
       End Select 
       CurChr += 1 
      Loop 
     Catch ex As Exception 
      MsgBox(ex.Message, MsgBoxStyle.OkOnly, "URLDecode") 
     End Try 
     Return oRet 
    End Function 
End Class 

Original Question

Je travaille sur un projet qui nécessite la lecture d'un document XML, en particulier sauvé formulaire à partir de Microsoft InfoPath.

Voici un exemple simple de ce que je vais travailler avec ainsi que quelques informations de fond qui pourraient être utiles:

<?xml version="1.0" encoding="UTF-8"?> 
<?mso-infoPathSolution solutionVersion="1.0.0.2" productVersion="12.0.0" PIVersion="1.0.0.0" href="file:///C:\Users\darren\Desktop\simple_form.xsn" name="urn:schemas-microsoft-com:office:infopath:simple-form:-myXSD-2009-05-15T14-16-37" ?> 
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?> 
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-05-15T14:16:37" xml:lang="en-us"> 
    <my:first_name>John</my:first_name> 
    <my:last_name>Doe</my:last_name> 
</my:myFields> 

Mon objectif maintenant est d'extraire le versionID et l'emplacement de la forme. Assez facile avec regex:

Dim _doc As New XmlDocument 
_doc.Load(_thefile) 
Dim oRegex As String = "^solutionVersion=""(?<sVersion>[0-9.]*)"" productVersion=""(?<pVersion>[0-9.]*)"" PIVersion=""(?<piVersion>[0-9.]*)"" href=""(?<href>.*)"" name=""(?<name>.*)""$" 
Dim rx As New Regex(oRegex), m As Match = Nothing 
For Each section As XmlNode In _doc.ChildNodes 
    m = rx.Match(section.InnerText.Trim) 
    If m.Success Then 
     Dim temp As String = m.Groups("name").Value.Substring(m.Groups("name").Value.ToLower.IndexOf("infopath") + ("infopath").Length + 1) 
     fileName = temp.Substring(0, temp.LastIndexOf(":")) 
     fileVersion = m.Groups("sVersion").Value 
    End If 
Next 

Le seul problème que cette solution de travail soulève est de savoir si les changements de schéma dans l'en-tête du document InfoPath ... par exemple les propriétés de version de la solution et la version du produit de swap emplacements (Microsoft LOVES faire des choses comme ça, il semble).

J'ai donc choisi d'utiliser la capacité d'analyse XML de VB.NET pour atteindre les résultats ci-dessus, sans-regex.

Le ChildNode de l'objet _doc qui contient l'information nécessaire, mais il n'a pas ChildNodes:

_doc.ChildNode(1).HasChildNodes = False 

Quelqu'un peut-il me aider avec ça?

Répondre

1

Les instructions de traitement font partie du document XML, mais leurs attributs ne sont pas analysés. Essayez ce code:

// Load the original xml... 
var xml = new XmlDocument(); 
xml.Load(_thefile); 

// Select out the processing instruction... 
var infopathProcessingInstruction = xml.SelectSingleNode("/processing-instruction()[local-name(.) = \"mso-infoPathSolution\"]"); 

// Since the processing instruction does not expose it's attributes, create a new XML document... 
var xmlInfoPath = new XmlDocument(); 
xmlInfoPath.LoadXml("<data " + infopathProcessingInstruction.InnerText + " />"); 

// Get the data... 
var solutionVersion = xmlInfoPath.DocumentElement.GetAttribute("solutionVersion"); 
var productVersion = xmlInfoPath.DocumentElement.GetAttribute("productVersion"); 
+0

Génial, merci pour ça! – Anders

+0

Une chose cependant, pourriez-vous expliquer la ligne qui définit la variable infopathProcessingInstruction?Comme je l'ai mentionné dans la question je suis nouveau à la manipulation XML, donc je ne vois pas exactement comment cette ligne accomplit ce qu'elle fait: P – Anders

+0

Le XPath sur la ligne "var infopathProcessingInstruction" dit "donnez-moi la première instruction de traitement qui a un nom de "mso-infoPathSolution" Cette URL peut vous aider: http://aspalliance.com/515 – David

0

Le problème est que les balises que vous voulez analyser ne font pas vraiment partie du document XML. Ce sont les XML-Prolog contenant les instructions de traitement. Et donc ils ne seront pas disponibles dans le XmlDocument en tant qu'éléments. Ma seule idée serait (à part regarder dans la documentation comment on pourrait accéder à ces éléments) de déplacer seulement l'élément mso-infoPathSolution dans un XmlDocument de lui-même, après avoir déshabillé le <? ? > et les remplacer par < />. Ensuite, vous pouvez accéder aux attributs indépendamment de leur commande.

+0

Des idées comment insérer ce nœud particulier dans un nouveau XmlDocument? Je suis relativement nouveau dans l'analyse et la manipulation Xml. Actuellement j'essaye de modifier le OuterXml de newNode, mais c'est ReadOnly ainsi la quête continue! – Anders

Questions connexes