VB.NET возникли проблемы с записью строки в корневой узел

#xml #vb.net

#xml #vb.net

Вопрос:

         Dim doc As New XmlDocument()
        Dim nodes As XmlNodeList
        doc.Load("test.xml")
        nodes = doc.SelectNodes("/Subjects/" amp; comboSubject.Text)

        Dim fileName As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.xml")

        Dim Rows As List(Of DataGridViewRow) =
            gridTests.Rows.Cast(Of DataGridViewRow).Where(Function(row) Not row.IsNewRow).ToList

        Dim xmlData As String =
        <<%= comboSubject.Text %>>
            <%= From row In Rows
                Select
                    <attempt>
                        <test><%= CStr(row.Cells("Test").Value) %></test>
                        <score><%= CStr(row.Cells("Score").Value) %></score>
                    </attempt> %>
        </>.ToString


        For Each node As XmlNode In nodes
            If node IsNot Nothing Then
                node.ParentNode.RemoveChild(node)
                doc.Save("test.xml")
            End If
        Next
  

Как мне записать строку xmlData в узел Subjects?

 <?xml version="1.0" encoding="UTF-8"?>
<Subjects>
  <History>
    <attempt>
      <test>1999</test>
      <score>75</score>
    </attempt>
    <attempt>
      <test>1987</test>
      <score>50</score>
    </attempt>
    <attempt>
      <test>1789</test>
      <score>25</score>
    </attempt>
  </History>
</Subjects>
  

Всякий раз, когда я пытаюсь записать строку XmlData в test.xml в итоге либо все удаляется, либо вообще ничего не делается. Я не уверен, что я здесь делаю не так. Любое решение этой проблемы было бы очень оценено.

Ответ №1:

Я вижу несколько проблем…

 Dim xmlData As String =
        <<%= comboSubject.Text %>>
            <%= From row In Rows
                Select
                    <attempt>
                        <test><%= CStr(row.Cells("Test").Value) %></test>
                        <score><%= CStr(row.Cells("Score").Value) %></score>
                    </attempt> %>
        </>.ToString
  

Похоже, что это не приводит к созданию допустимого XML, поскольку тег закрыт неправильно. Это должно быть, например, </History> вместо </>

Кроме того, вы ничего не делаете с этим XML, кроме как сохраняете его в переменной xmlData. Переменная никогда не используется. Вы продолжаете удалять только существующий узел, вот почему вы видите надпись «удалить все»

 For Each node As XmlNode In nodes
    If node IsNot Nothing Then
        node.ParentNode.RemoveChild(node)
        doc.Save("test.xml")
    End If
Next
  

doc представляет весь ваш документ и node было бы, например, так, /Subjects/History поэтому, когда вы говорите, что node.ParentNode.RemoveChild(node) вы удаляете History узел из его родительского Subjects узла, оставляя вам только <Subjects/> сохраняемый. Этот цикл также вызывал бы save для каждой итерации, в которой нет необходимости, но это ни здесь, ни там.

Наконец, как упоминалось, вы нигде не записываете xmlData обратно в документ. Не существует отличного ответа на вопрос, как это сделать, потому что XML не предназначен для создания в виде строки таким образом. Вы можете использовать XmlNode.Свойство InnerXml напрямую изменять разметку элемента, но, как отмечает Microsoft в документе, это не лучшая идея. Вы также могли бы разобрать эту строку в объект XML, но в идеале вы должны просто создавать объекты узла для каждого из создаваемых вами элементов, а затем добавлять их в doc в соответствующем месте. Что-то вроде этого, в качестве примера:

 Dim objHistory as XmlElement = doc.CreateElement("History")
Dim objAttempt As XmlElement = doc.CreateElement("attempt")
Dim objTest As XmlElement = doc.CreateElement("test")
Dim objScore as XmlElement = doc.CreateElement("score")
objTest.InnerText = "1999"
objScore.InnerText = "75"
objAttempt.AppendChild(objTest)
objAttempt.AppendChild(objScore)
objHistory.AppendChild(objAttempt)
doc.FirstChild.AppendChild(objHistory)