使用以前从属性节点新创建的字符串向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

这是我在这里的第一篇文章。感谢mil邀请我参加,如果我在第一次尝试中犯了错误或造成误解,请道歉。我的难题如下: 我编写了一个小脚本,用于更新一些第三方软件组件,这需要更改具有以下结构的XML文件:

<?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")