Dies ist mein erster Beitrag hier. Tausend Dank, dass Sie mich um sich haben und es tut mir leid, wenn ich bei diesem ersten Versuch Fehler mache oder Missverständnisse erzeuge. Mein Rätsel ist wie folgt: ich ein kleines Skript geschrieben, einige Drittanbieter-Software-Komponenten für die Aktualisierung, die erfordert, Ändern eine XML-Datei mit der folgenden Struktur:Hinzufügen eines Elements zu einem XML-Dokument mit einer zuvor neu erstellten Zeichenfolge von einem Attributknoten
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>xxx</ProjectGuid>
<OutputType>xxx</OutputType>
<StartupObject>xxx</StartupObject>
<RootNamespace>xxx</RootNamespace>
<AssemblyName>xxx</AssemblyName>
<FileAlignment>xxx</FileAlignment>
<MyType>WindowsFormsWithCustomSubMain</MyType>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<SccProjectName>xxx</SccProjectName>
<SccLocalPath>xxx</SccLocalPath>
<SccAuxPath>xxx</SccAuxPath>
<SccProvider>xxx</SccProvider>
</PropertyGroup>
<PropertyGroup>
...
<ItemGroup>
<Reference Include="someString, Version=123, Culture=neutral, PublicKeyToken=ab1, processorArchitecture=xxx">
<SpecificVersion>False</SpecificVersion>
<Private>True</Private>
</Reference>
Die fraglichen Funktion einen Teil aus dem Attribute nimmt umfassen und sollte idealerweise zu einem neu erstellten XML-Element hinzugefügt werden (zB <HintPath>xyz</HintPath>
). Das Auswählen des Attributs und das Abrufen der Zeichenfolge funktionierte, sobald ich das Namespace-Problem umgehen konnte (dank StackOverflow). Wenn ich jedoch das HintPath-Element mithilfe von AppendChild hinzufüge, erhalte ich die Fehlermeldung, dass das Objekt nicht korrekt referenziert wird. Ich habe versucht, LINQ zu verwenden, um das Problem zu beheben, konnte jedoch die Abfrage Syntax nicht umgehen (da ich gewohnt bin, XPath zu verwenden). Wenn jemand eine LINQ-Lösung hat, lassen Sie es mich wissen.
Dies ist mein Code so weit (XPath-Ansatz)
Private Function getAttributInclude(ByVal path2xml As String) As List(Of String)
Dim xmlDoc As XmlDocument = New XmlDocument()
Dim listAttributValues As New List(Of String)
Dim nodeAttributInsertValueSplitted() As String
Dim splittedStringMitEndungDll As String
Dim nsmanager As XmlNamespaceManager = New XmlNamespaceManager(xmlDoc.NameTable)
nsmanager.AddNamespace("msn", "http://schemas.microsoft.com/developer/msbuild/2003")
nsmanager.AddNamespace(String.Empty, "urn:test") 'default namespace
xmlDoc.Load(path2xml)
Dim nodeListAttributInclude As XmlNodeList
Dim root As XmlElement = xmlDoc.DocumentElement
nodeListAttributInclude = root.SelectNodes("/Project/ItemGroup/Reference/@Include")
Dim nodeAttributeInclude As XmlNode
Dim hintPath As XmlElement
For Each nodeAttributeInclude In nodeListAttributInclude
nodeAttributInsertValueSplitted = nodeAttributeInclude.Value.Split(",")
splittedStringMitEndungDll = String.Format("..\..\lib\{0}.dll", nodeAttributInsertValueSplitted(0))
listAttributValues.Add(nodeAttributeInclude.InnerText)
hintPath = xmlDoc.CreateElement("HintPath", nodeAttributeInclude.NamespaceURI)
hintPath.InnerText = splittedStringMitEndungDll
nodeAttributeInclude.ParentNode.AppendChild(hintPath)
Next
xmlDoc.Save(path2xml)
Return listAttributValues
ich besonders gefragt, warum .AppendChild ist in diesem Fall nicht
Dank mil im Voraus für jede Hilfe zur Verfügung gestellt zu arbeiten.
Dear all
würde Genau wie Sie ein Update geben. Ich kam zurück zu dem Projekt und bekam einen guten Ansatz. Es stellte sich jedoch heraus, dass dies nur ein Schritt in die richtige Richtung war, und ich könnte dafür verantwortlich sein, dass ich nicht explizit geschrieben habe, was ich mit dem Original beabsichtigte. Der neue Code-Schnipsel ist wie folgt: Dim xDoc Wie XDocument = XDocument.Load (path2xml)
Dim nsmanager As New XmlNamespaceManager(New NameTable)
nsmanager.AddNamespace("ns", "http://schemas.microsoft.com/developer/msbuild/2003")
nsmanager.AddNamespace(String.Empty, "urn:test") 'default namespace
Dim ns As XNamespace = "http://schemas.microsoft.com/developer/msbuild/2003"
Dim xAttr = xDoc.XPathSelectElement("//ns:Reference", nsmanager).Attribute("Include").Value
Dim hpElement As New XElement(New XElement(ns + "HintPath", xAttr))
xDoc.XPathSelectElement("//ns:Reference", nsmanager).Add(hpElement)
xDoc.Save(path2xml)
Bisher das XML-Element entsprechend erstellt wird. Mit dem Xpath-Ausdruck dachte ich, dass ich alle Elemente mit dem gesuchten Attribut bekommen würde. Außerdem hätte ich am Anfang gerne eine Nodeliste erhalten, da ich für jeden Knoten/jedes Element, der das Attribut enthält, Ersatz für die Attribut-Zeichenkette anwenden würde. Es stellte sich heraus, dass nur das erste Element mit Ihrem Vorschlag ausgewählt wurde. Hier sind meine neuen Fragen: 1. Ist es möglich, alle Knoten mit dieser Syntax auszuwählen? 2. Wie würde ich die String-Ersetzung (n) in jedem Attributknoten ausführen? Bitte beziehen Sie sich auf meinen ursprünglichen Beitrag, indem Sie meine ursprüngliche Idee anhand einer Knotenliste und Iteration über jeden Knoten für die Ersetzungen zeigen. aber ich konnte das XML-HintPath-Element am Ende nicht erstellen). Ich glaube, ich wurde auf dem Weg aufgrund meiner fehlenden Programmiererfahrung verwirrt, tut mir leid, dass Wäre großartig, wenn Sie oder jemand anderes mehr Licht auf dieses Thema werfen könnte.
Update: Ich hatte ein anderer auf den Code gehen, und es gibt eine Sache, die ich nicht verstehe überhaupt: jede Zeile in dem Codeblock oben erneut geprüft haben, ich auf die folgende Zeile kam:
xDoc.XPathSelectElement("//ns:Reference", nsmanager).Add(hpElement)
Die Beschreibung der Parameter und Rückgabewerte besagt, dass ein einzelner Wert retrended würde. Ich gebe zu, dass ich diese speziellen Informationen vorher nicht gelesen habe. Ich sah jedoch, dass eine Pluralversion, d. H. XPathSelectElements, ebenfalls möglich war. Nach meinem Verständnis schien das ein guter Ansatz (und ein leichter, aber allzu typischer Tippfehler).Zu meiner großen Überraschung beim Wechsel der Linie
xDoc.XPathSelectElements("//ns:Reference", nsmanager).Add(hpElement)
bekam ich eine Fehlermeldung, dass
Attribute is not a member of System.Collection.Generic.IEnumerable(Of System.Xml.Linq.XElement
Das ist genau das, was ich nicht verstehe. Wie kann die Auswahl aller Elemente falsch sein? Und wie ist es möglich, eine Liste aller durch den XPAth Expression ausgewählten Knoten zur weiteren Verarbeitung zu bekommen? Ich bin jetzt ziemlich ratlos. Ich freue mich auf Ihre Antworten.
Ich versuchte die folgenden Ansätze in diesem und anderen Foren gefunden.
Dim xAttr = xDoc.XPathSelectElement("//ns:Reference", nsmanager).Attribute("Include").Value
Dim xAttr = xDoc.Root.Descendants("Reference").Attributes("Include")
Dim xAttr = xDoc.XPathEvaluate("//Reference/@Include")
Allerdings scheint keiner dieser Ansätze zu funktionieren. Ich kann die Attribut-Zeichenfolge nicht auswählen und die Ersetzungen entsprechend ausführen. Vielleicht hilft das bei der Identifizierung des Problems.
Update: Ich habe einen anderen Blick auf meinen vorherigen Code und war in der Lage, einige Probleme zu lösen (siehe Code unten). Ich kann jetzt alle Knoten auswählen, die ich mir vorgestellt habe. Außerdem scheinen im Debug-Modus auch die Ersetzungen anzustoßen. Allerdings, und das fängt an, mich zu ärgern, ich kann nicht herausfinden, wie man das Neue mit einigen der ersetzten Saiten hinzufügt. Das Beispiel von Microsoft
uses XmlNode root = doc.DocumentElement;
Was Ich mag würde uns tun aacomplish den bereits vorhandenen XPath-Ausdruck für das Element verwendet wird. Während ich versuche, bekomme ich normalerweise einen Fehler, dass das Objekt 'x' nicht in Objekt 'y' umgewandelt werden kann. Könnte mir bitte jemand helfen, dieses Problem zu lösen?
Dies ist der neue Code
Private Function getAttributInclude(ByVal pfad2xml As String) As XmlDocument
Dim xDoc As New XmlDocument
xDoc.Load(pfad2xml)
Dim ns As XNamespace = "http://schemas.microsoft.com/developer/msbuild/2003"
Dim nsmanager As New XmlNamespaceManager(New NameTable)
nsmanager.AddNamespace("ns", "http://schemas.microsoft.com/developer/msbuild/2003")
nsmanager.AddNamespace(String.Empty, "urn:test")
Dim navigator As XPathNavigator = xDoc.CreateNavigator()
Dim xpathAttributInclude As XPathExpression = XPathExpression.Compile("//ns:Reference/ns:SpecificVersion/../@Include")
xpathAttributInclude.SetContext(nsmanager)
Dim xpathElementSpecificVersion As XPathExpression = XPathExpression.Compile("//ns:Reference/ns:SpecificVersion")
xpathElementSpecificVersion.SetContext(nsmanager)
Dim nodeListAttributInclude As XPathNodeIterator = navigator.Select(xpathAttributInclude)
Dim nodeListElementSpecificVersion As XPathNodeIterator = navigator.Select(xpathElementSpecificVersion)
Dim hintPath As XmlElement
For Each nodeAttributInclude In nodeListAttributInclude
Dim nodeAttributInsertValueSplitted = nodeAttributInclude.Value.Split(",")
Dim replacedNodeText As String
Dim splittedStringMitEndungDll
Dim replacedVersionAttribut As String
replacedNodeText = nodeAttributInsertValueSplitted(0).ToString.Replace(_
txtBoxEnterVersionNummerOld.Text, txtBoxEnterVersionNummerNew.Text)
writeLog(replacedNodeText + vbCrLf)
splittedStringMitEndungDll = String.Format("..\..\lib\{0}.dll", replacedNodeText)
writeLog(splittedStringMitEndungDll + vbCrLf)
If tbXmlDevExpressVersionNew.Text.Length > 0 Then
Dim splittedElementSpecificVersion = nodeAttributInsertValueSplitted(1).Split("=")
replacedVersionAttribut = splittedElementSpecificVersion(1).ToString.Replace(_
splittedElementSpecificVersion(1).ToString, tbXmlDevExpressVersionNew.Text)
writeLog(replacedVersionAttribut + vbCrLf)
Else
MessageBox.Show("Please enter a valid version numbers")
End If
hintPath = xDoc.CreateElement("HintPath", nodeAttributInclude.NamespaceURI)
hintPath.InnerText = splittedStringMitEndungDll
Dim node2insertAfter = xDoc.DocumentElement
For Each nodeElementSpecificVersion In nodeListElementSpecificVersion
xDoc.InsertAfter(hintPath, node2insertAfter.SelectSingleNode("//Reference/SpecificVersion"))
writeLog(nodeElementSpecificVersion.ToString + vbCrLf)
Next
Next
xDoc.Save("c:\tmp\result_xml.xml")
Return xDoc
End Function
Update: ich auf eine interesting article kam, dass man Streptokokken auf eine Lösung zur Verfügung gestellt. Allerdings habe ich immer noch das Problem, dass das betreffende Element nur an das letzte Element angehängt wird, obwohl ich eine Schleife in einer Schleife verwende. Außerdem scheint der Ersatz nicht zu greifen. Hier ist ein Ausschnitt aus dem angepassten appendChild Abschnitt zum Hinzufügen der XML-Elemente
For Each nodeElementReference In nodeListElementReference
Dim node2StartInsert = DirectCast(nodeElementReference, System.Xml.IHasXmlNode).GetNode
node2StartInsert.AppendChild(hintPath)
Next
Dank einer mil im Voraus für Ihre assisstance.
Mit freundlichen Grüßen Sas
ich eine Lösung finden verwaltet. Der Code muss jedoch nur zum Extrahieren des Attributs verwendet werden, das jetzt korrekt in der XML-Eingabedatei enthalten ist, auf die dieser Code angewendet wird. Die Verwendung von XMLElement und XPathNavigator bot die Möglichkeit, das zusätzliche Element in die vorhandene XML-Datei zu schreiben.
Dim hintPath As XmlElement
Dim nodeAttributInclude As XPathNavigator
For Each nodeAttributInclude In nodeListAttributInclude
Dim nodeAttributInsertValueSplitted = nodeAttributInclude.Value.Split(",")
Dim versionsInfoText As String
Dim splittedStringMitEndungDll
versionsInfoText = nodeAttributInsertValueSplitted(0).ToString
splittedStringMitEndungDll = String.Format("..\..\lib\{0}.dll", versionsInfoText)
nodeAttributInclude.MoveToParent()
hintPath = xDoc.CreateElement("HintPath")
hintPath.InnerText = splittedStringMitEndungDll
nodeAttributInclude.AppendChild("<HintPath>" + hintPath.InnerText + "</HintPath>")
Next
xDoc.Save("c:\tmp\result_xml.xml")
Update: Ich habe einige Kontrollen und fand heraus, dass die XPath Notationen erscheinen nicht ausgewertet werden. Ich habe den relativen und absoluten Pfad Notation versucht. Die Auswahl von nur // @ Include führte jedoch wie erwartet zu einer Nodelist.Ich bin mir nicht sicher, aber ich nehme an, dass die XPath-Implementierung möglicherweise kaputt ist. Wäre großartig, wenn jemand eine Erklärung hinzufügen könnte. – Sasquatch
Jemand wies darauf hin, dass nicht klar war, welches Dokument meine Quell- und Zieldatei war. Die Eingabedatei ist der hier veröffentlichte XML-Code. Die Ausgabedatei soll identisch sein, aber das zusätzliche XML-Element muss hinzugefügt werden ( sollte daher ein anderes untergeordnetes Element mit dem Namen erhalten, das wiederum die geänderte Teilzeichenfolge enthält). Ich hoffe, das hilft für weitere Diskussionen –
Sasquatch
Um genauer zu sein über den Fehler. Das Problem ist, dass "System.Xml.XmlNodeList" nicht in "System.Xml.XmlNode" konvertiert werden kann. Die Frage ist, wie ich zu den Knoten gelangen soll, die für das Finden der korrekten Position für InsertAfter benötigt werden, wenn keine Knotenliste verwendet wird. Ich dachte auch, dass die Schleife dafür sorgen würde. Ich bin jetzt ziemlich verwirrt und ratlos. – Sasquatch