Разбор xml в F #, когда файл имеет атрибут xmlns

Поэтому я попытался использовать сообщение о синтаксическом анализе F # XML в следующем xml (из uclassify API):

<?xml version="1.0" encoding="UTF-8" ?> 
<uclassify xmlns="http://api.uclassify.com/1/ResponseSchema" version="1.01"> 
    <status success="true" statusCode="2000"/> 
    <readCalls> 
    <classify id="cls1"> 
        <classification textCoverage="1"> 
            <class className="happy" p="0.912929"/> 
            <class className="upset" p="0.0870707"/> 
        </classification> 
    </classify> 
    </readCalls> 
</uclassify>

Код выглядит примерно так:

let doc  = 
    Xdocument.Load file
doc.Element(xn "uclassify")
   .Element(xn "readCalls")
   .Element(xn "classify")
   .Element(xn "classification")
   .Element(xn "class").Attribute(xn "p")

Это не работает!!! Кажется, это не может выполнить синтаксический анализ. Но удаление атрибута xmlns="http://api.uclassify.com/1/ResponseSchema" version="1.01" заставляет его работать:

let doc  = 
    Xdocument.Load file
    let test = IO.File.ReadAllText(file).Replace("xmlns=\"http://api.uclassify.com/1/ResponseSchema\" version=\"1.01\"","")
    XDocument.Parse(test)

doc.Element(xn "uclassify")
   .Element(xn "readCalls")
   .Element(xn "classify")
   .Element(xn "classification")
   .Element(xn "class").Attribute(xn "p")

Обратите внимание, что эта проблема связана с Почему должен Удаляю атрибут xmlns .... Возникает вопрос, почему я должен удалить атрибут xmlns? Что мне следует использовать для синтаксического анализа XML с атрибутом xmlns?

Спасибо


person jlezard    schedule 03.05.2011    source источник


Ответы (2)


Версия @dahlbyk работает, но как только у вас есть объект XNamespace, вы можете добавить к нему строку в F # так же, как вы можете в C #. В результате я бы предпочел этот синтаксис, поскольку он немного ближе к тому, как это обычно делается в C #:

let xn = XName.Get
let xmlns = XNamespace.Get

let ns = xmlns "http://api.uclassify.com/1/ResponseSchema"

doc.Element(ns + "uclassify")
   .Element(ns + "readCalls")
   .Element(ns + "classify")
   .Element(ns + "classification")
   .Element(ns + "class")
   .Attribute(xn "p")
person Joel Mueller    schedule 03.05.2011
comment
Это также будет немного быстрее ;-). - person Eamon Nerbonne; 04.05.2011

Вам нужно ссылаться на элементы с их пространством имен:

let xn (tag:string) = XName.Get(tag)
let xnuc (tag:string) = XName.Get(tag, "http://api.uclassify.com/1/ResponseSchema")

doc.Element(xnuc "uclassify")
   .Element(xnuc "readCalls")
   .Element(xnuc "classify")
   .Element(xnuc "classification")
   .Element(xnuc "class")
   .Attribute(xn "p")
person dahlbyk    schedule 03.05.2011
comment
Не знаю подробностей linq-to-xml, но, возможно, это будет немного быстрее: let xnuc = XNamespace.Get("http://api.uclassify.com/1/ResponseSchema").GetName - person Eamon Nerbonne; 03.05.2011
comment
В C # принято делать что-то вроде var ns = XNamespace.Get(...) и doc.Element(ns + "uclassify"), но F # плохо работает с неявным приведением типов, поэтому функции для создания XName из string. - person dahlbyk; 03.05.2011