使用以前从属性节点新创建的字符串向XML文档添加元素
这是我在这里的第一篇文章。感谢mil邀请我参加,如果我在第一次尝试中犯了错误或造成误解,请道歉。我的难题如下: 我编写了一个小脚本,用于更新一些第三方软件组件,这需要更改具有以下结构的XML文件:使用以前从属性节点新创建的字符串向XML文档添加元素,xml,vb.net,linq,xpath,Xml,Vb.net,Linq,Xpath,这是我在这里的第一篇文章。感谢mil邀请我参加,如果我在第一次尝试中犯了错误或造成误解,请道歉。我的难题如下: 我编写了一个小脚本,用于更新一些第三方软件组件,这需要更改具有以下结构的XML文件: <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuil
<?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>
我特别想知道为什么,这个孩子在这种情况下不工作
提前感谢mil提供的任何帮助
各位亲爱的
我只是想给你一个更新。
我回到项目中,得到了一个很好的方法。然而,事实证明,这只是朝着正确方向迈出的一步,我可能要为没有明确地写下我对原文的意图而受到责备。新代码段如下所示:
作为XDocument的Dim xDoc=XDocument.Load(路径2xml)
到目前为止,正在相应地创建XML元素。但是,使用Xpath表达式,我想我会得到所有元素都具有我要查找的属性。此外,我最初希望获得一个节点列表,因为我将对包含该属性的每个节点/元素的属性字符串应用替换。事实证明,使用您的建议只选择了第一个元素。
以下是我的新问题:
1.是否可以使用此语法选择所有节点?
2.如何在每个属性节点中执行字符串替换
请参阅我的第一篇文章,它向您展示了我最初使用节点列表并迭代每个节点进行替换的想法(这种方法有效,但我最终无法创建XMLHintPath元素)。我想我是因为缺乏编程经验而被弄糊涂了,很抱歉
如果你或其他任何人能在这个话题上透露更多的信息,那就太好了
更新:
我又试了一遍代码,有一件事我根本不明白:在重新检查了上面代码块中的每一行之后,我遇到了下面这一行:
xDoc.XPathSelectElement("//ns:Reference", nsmanager).Add(hpElement)
参数和返回值的描述表示将检索单个值。我承认我之前没有读到那个特别的信息。但是,我看到复数版本,即XPathSelectElements也是可能的。根据我的理解,这似乎是一个很好的方法(和一个轻微但非常典型的打字错误)。当我把线路改为
xDoc.XPathSelectElements("//ns:Reference", nsmanager).Add(hpElement)
我说这话有错
Attribute is not a member of System.Collection.Generic.IEnumerable(Of System.Xml.Linq.XElement
这正是我不明白的。选择所有元素怎么可能是错误的?如何获得XPAth表达式选择的所有节点的列表以供进一步处理?我现在很茫然。期待您的回复
我尝试了在这个论坛和其他论坛中找到的以下方法
Dim xAttr = xDoc.XPathSelectElement("//ns:Reference", nsmanager).Attribute("Include").Value
Dim xAttr = xDoc.Root.Descendants("Reference").Attributes("Include")
Dim xAttr = xDoc.XPathEvaluate("//Reference/@Include")
然而,这些方法似乎都不起作用。我无法选择属性字符串并相应地执行替换。也许这有助于识别问题
更新:
我再次查看了我以前的代码,并能够解决一些问题(参见下面发布的代码)。我现在可以选择我设想的所有节点。此外,在调试模式下,替换似乎也开始生效。然而,这真的开始让我恼火了,我不知道如何添加新的替换字符串。微软提供的例子
uses XmlNode root = doc.DocumentElement;
我想做的是使用元素已经存在的Xpath表达式来完成我们的工作。在尝试时,我通常会得到一个错误,对象“x”无法转换为对象“y”。有人能帮我解决这个问题吗
这是新代码
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
更新:
我遇到了一个问题,它提供了一个解决方案。然而,我仍然有一个问题,即所讨论的元素仅附加到最后一项,尽管我在循环中使用循环。此外,替换似乎也没有生效
For Each nodeElementReference In nodeListElementReference
Dim node2StartInsert = DirectCast(nodeElementReference, System.Xml.IHasXmlNode).GetNode
node2StartInsert.AppendChild(hintPath)
Next
提前感谢你的帮助
问候
Sas
我设法找到了解决办法。但是,代码只需要提取属性,该属性现在正确地存在于该代码应用到的输入XML中。同时使用XMLElement和XPathNavigator提供了将附加元素写入现有XML文件的方法
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")
Dim hintPath作为XmlElement
昏暗的节点属性包括XPathNavigator
对于每个节点,属性包含在节点属性包含中
Dim nodeAttributInsertValueSplitted=nodeAttributInclude.Value.Split(“,”)
Dim versionInfoText作为字符串
Dim splittedStringMitEndungDll
VersionInfoText=NodeAttributenServaleTValueSplitted(0)。ToString
splittedStringMitEndungDll=String.Format(“..\..\lib\{0}.dll”,版本信息文本)
nodeAttributenclude.MoveToParent()
hintPath=xDoc.CreateElement(“hintPath”)
hintPath.InnerText=拆分的StringMitendungDLL
NodeAttributeClude.AppendChild(“+hintPath.InnerText+”)
下一个
Save(“c:\tmp\result\u xml.xml”)
我设法找到了解决办法。但是,代码只需要提取属性,该属性现在正确地存在于该代码应用到的输入XML中。同时使用XMLElement和XPathNavigator提供了将附加元素写入现有XML文件的方法。
作为XmlElement的Dim hintPath
昏暗的节点属性包括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")
用于每个节点的NodeAttributeClude中的NodeAttributeClude
Dim nodeAttributInsertValueSplitted=nodeAttributInclude.Value.Split(“,”)
Dim versionInfoText作为字符串
Dim splittedStringMitEndungDll
VersionInfoText=NodeAttributenServaleTValueSplitted(0)。ToString
splittedStringMitEndungDll=String.Format(“..\..\lib\{0}.dll”,版本信息文本)
nodeAttributenclude.MoveToParent()
hintPath=xDoc.CreateElement(“hintPath”)
hintPath.InnerText=拆分的StringMitendungDLL
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")