2012-06-09 5 views
2
<location> 
    <hotspot name="name1" X="444" Y="518" /> 
    <hotspot name="name2" X="542" Y="452" /> 
    <hotspot name="name3" X="356" Y="15" /> 
</location> 

У меня есть переменная точки, и мне нужно выбрать узел с его координатами, а затем изменить значение атрибута. Я хочу сделать что-то похожее на:Выберите узел XML по значению атрибута

let node = xmld.SelectSingleNode("/location/hotspot[@X='542' @Y='452']") 
node.Attributes.[0].Value <- "new_name2" 

но принимает значения атрибутов с помощью переменной (variable_name.X/variable_name.Y).

+0

Не могли бы вы просто перебрать, сравнить атрибуты, а затем изменить правильный? –

+1

Чтобы иметь строго типизированный класс для XML-файла, вы должны десериализовать XML для объекта. Взгляните на утилиту xsd, чтобы сгенерировать базовый код. В противном случае ... просто реализуйте пользовательский ридер, ваш код будет использовать читатель, и он получит только структуры (а не raw XML). –

ответ

2

Это было очень легко. Предположив я хочу изменить первый атрибут в моем узле:

let node = xmld.SelectSingleNode("/location/hotspot[@X='" + string(current.X) + "'] [@Y='" + string(current.Y) + "']") 
node.Attributes.[0].Value <- v 

где «текущая» моя переменная;)

3

Лично я хотел бы использовать LINQ для XML:

var doc = XDocument.Load(...); 
var node = doc.Root 
       .Elements("hotspot") 
       .Single(h => (int) h.Attribute("X") == x && 
          (int) h.Attribute("Y") == y); 

Обратите внимание, что вы должны использовать SingleOrDefault, если там не может быть каких-либо элементов, соответствующих или First/FirstOrDefault если может быть несколько матчей.

После того, как вы нашли правильный hotspot узел, вы можете задать атрибуты легко:

node.SetAttributeValue("X", newX); 
node.SetAttributeValue("Y", newY); 
+0

интересно, я кое-что изучу в LINQ. Кажется действительно полезным ... –

+0

@FrankLioty: О, это - и не только для XML. –

0

Вы не можете использовать выражение XPath для заполнения более одной переменной в то время. Единственное значение, возвращаемое выражением XPath (или, на более техническом уровне, SelectSingleNode, которое оценивает выражение XPath), является узлом Xml, идентифицированным выражением.

Как только у вас есть элемент <hotspot> как объект-узел, вам необходимо будет использовать API-интерфейсы DOM для чтения и записи значений атрибутов или, возможно, некоторых программных подпрограмм для автоматической передачи значений атрибутов в и из строго типизированного объекта данных ,

2

Может быть что-то, как это будет работать:

// Tries to find the element corresponding to a specified point 
let tryFindElementByPoint (xmlDoc : XmlDocument) point = 
    let pointElement = 
     point 
     ||> sprintf "/location/hotspot[@X='%u' @Y='%u']" 
     |> xmlDoc.SelectSingleNode 

    match pointElement with 
    | null -> None 
    | x -> Some x 

// Finds the element corresponding to a specified point, then updates an attribute value on the element. 
let updatePointElement xmlDoc point (newValue : string) = 
    match tryFindElementByPoint xmlDoc point with 
    | None -> 
     point ||> failwithf "Couldn't find the XML element for the point (%u, %u)." 
    | Some node -> 
     // TODO : Make sure this updates the correct attribute! 
     node.Attributes.[0].Value <- newValue 
2

попробовать это

//let node = xmld.SelectSingleNode("/location/hotspot[@X='542' and @Y='452']") 
let query = sprintf "/location/hotspot[@X='%d' and @Y='%d']" 
let node = xmld.SelectSingleNode(query 542 452) 
Смежные вопросы