Does anyone know of an existing means of creating an XML hierarchy programatically from an XPath expression?
For example if I have an XML fragment such as:
I liked Chris' version because it handled attributes in xpaths and the other solutions didn't (though it doesn't handle "text()" in the path that well which I fixed). I unfortunately had to use this in a VB app, so here's the conversion for that:
Private Sub SplitOnce(ByVal value As String, ByVal separator As String, ByRef part1 As String, ByRef part2 As String)
If (value IsNot Nothing) Then
Dim idx As Integer = value.IndexOf(separator)
If (idx >= 0) Then
part1 = value.Substring(0, idx)
part2 = value.Substring(idx + separator.Length)
Else
part1 = value
part2 = Nothing
End If
Else
part1 = ""
part2 = Nothing
End If
End Sub
Private Function createXPath(ByVal doc As XmlDocument, ByVal xpath As String) As XmlNode
Dim node As XmlNode = doc
Dim part As String
For Each part In xpath.Substring(1).Split("/")
Dim nodes As XmlNodeList = node.SelectNodes(part)
If (nodes.Count > 1) Then
Throw New Exception("Xpath '" + xpath + "' was not found multiple times!")
ElseIf (nodes.Count = 1) Then
node = nodes(0)
Continue For
End If
If (part.EndsWith("text()")) Then
' treat this the same as previous node since this is really innertext
Exit For
ElseIf (part.StartsWith("@")) Then
Dim anode As XmlAttribute = doc.CreateAttribute(part.Substring(1))
node.Attributes.Append(anode)
node = anode
Else
Dim elName As String = Nothing
Dim attrib As String = Nothing
If (part.Contains("[")) Then
SplitOnce(part, "[", elName, attrib)
If (Not attrib.EndsWith("]")) Then
Throw New Exception("Unsupported XPath (missing ]): " + part)
End If
attrib = attrib.Substring(0, attrib.Length - 1)
Else
elName = part
End If
Dim nextnode As XmlNode = doc.CreateElement(elName)
node.AppendChild(nextnode)
node = nextnode
If (attrib IsNot Nothing) Then
If (Not attrib.StartsWith("@")) Then
Throw New Exception("Unsupported XPath attrib (missing @): " + part)
End If
Dim name As String = ""
Dim value As String = ""
SplitOnce(attrib.Substring(1), "='", name, value)
If (String.IsNullOrEmpty(value) Or Not value.EndsWith("'")) Then
Throw New Exception("Unsupported XPath attrib: " + part)
End If
value = value.Substring(0, value.Length - 1)
Dim anode As XmlAttribute = doc.CreateAttribute(name)
anode.Value = value
node.Attributes.Append(anode)
End If
End If
Next
Return node
End Function