Andy
Andy

Reputation: 135

Overwriting element value based upon node attribute value

My xml document is structured as below:

<Root>
  <Word ID="23">
    <Type>auxiliary</Type>
    <English></English>
    <Thai></Thai>
    <Meaning></Meaning>
    <Audio>Dictionary Resources\Sound Files\23.wma</Audio>
    <Picture>Dictionary Resources\Picture Files\23.jpg</Picture>
    <Transliteration></Transliteration>
    <Timestamp />
  </Word>
...
</Root>

Each node has a unique attribute (ID). What I would like to do, is using the user input of the attribute, in this case, the int value 23, is to ammend the .Value of the timestamp.

In pseudo code, something like this:

    Sub Timestamp(ByVal IDChosen As String)
    Dim Dictionary As XDocument = XDocument.Load("Dictionary Resources\Dictionary.xml")
    Dictionary.Root.Elements("Word").Atrribute"ID"(IDChosen).Value = DateTime.Now
    Dictionary.Save("Dictionary Resources\Dictionary.xml")
    End Sub

Upvotes: 1

Views: 138

Answers (1)

Steven Doggart
Steven Doggart

Reputation: 43743

There are multiple ways of doing that. You can use the <> and @ syntax with the XDocument object to drill down to the desired element, like this:

Sub Timestamp(idChosen As String)
    Dim doc As XDocument = XDocument.Load("Dictionary Resources\Dictionary.xml")
    Dim word As XElement = doc.<Root>.<Word>.FirstOrDefault(Function(x) x.@ID = idChosen)
    If word IsNot Nothing Then
        word.<Timestamp>.First().SetValue(Date.Now)
        doc.Save("Dictionary Resources\Dictionary.xml")
    End If
End Sub

Or you could use XPath to select the element, like this:

Sub Timestamp(idChosen As String)
    Dim doc As XDocument = XDocument.Load("Dictionary Resources\Dictionary.xml")
    Dim timeStamp As XElement = doc.XPathSelectElement("/Root/Word[@ID='" & idChosen & "']/Timestamp")
    If timeStamp IsNot Nothing Then
        timeStamp.SetValue(Date.Now)
        doc.Save("Dictionary Resources\Dictionary.xml")
    End If
End Sub

Or, you could use query syntax to select the element, like this:

Sub Timestamp(idChosen As String)
    Dim doc As XDocument = XDocument.Load("Dictionary Resources\Dictionary.xml")
    Dim t As XElement = _
        (
        From word In doc.<Root>.<Word> 
        Where word.@ID = idChosen 
        Select word.<Timestamp>.FirstOrDefault()
        ).FirstOrDefault()
    If t IsNot Nothing Then
        t.SetValue(Date.Now)
        doc.Save("Dictionary Resources\Dictionary.xml")
    End If
End Sub

Or, if you want to use the query syntax without using the <> and @ syntax, you could do it, like this:

Sub Timestamp(idChosen As String)
    Dim doc As XDocument = XDocument.Load("Dictionary Resources\Dictionary.xml")
    Dim t As XElement = _
        (
        From word In doc.Root.Elements("Word") 
        Where word.Attributes("ID").Any(Function(x) x.Value = idChosen) 
        Select word.Element("Timestamp")
        ).FirstOrDefault()
    If t IsNot Nothing Then
        t.SetValue(Date.Now)
        doc.Save("Dictionary Resources\Dictionary.xml")
    End If
End Sub

Or, if you don't care about the actual XML document structure, and you just want to find the first Word element with that ID, regardless of where it resides in the document tree, you can do select the element like this:

Dim word As XElement = doc...<Word>.FirstOrDefault(Function(x) x.@ID = idChosen)

Or:

Dim timeStamp As XElement = doc.XPathSelectElement("//Word[@ID='" & idChosen & "']/Timestamp")

Or:

Dim t As XElement = _
    (
    From word In doc.Descendants("Word") 
    Where word.@ID = idChosen 
    Select word.<Timestamp>.FirstOrDefault()
    ).FirstOrDefault()

Or:

Dim t As XElement = _
    (
    From word In doc.Descendants("Word") 
    Where word.Attributes("ID").Any(Function(x) x.Value = idChosen) 
    Select word.Element("Timestamp")
    ).FirstOrDefault()

Personally, I would recommend using the XPath method of selecting the node, since it's short, simple, easy to read, and it's using an industry-standard query language rather than Microsoft's proprietary LINQ technology, but that's just me :)

Upvotes: 1

Related Questions