【问题标题】:Parsing xml in F# when file has xmlns attribute当文件具有 xmlns 属性时在 F# 中解析 xml
【发布时间】:2011-05-03 13:06:58
【问题描述】:

所以我尝试在以下 xml 上使用 F# XML parsing post(来自 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")

注意这个问题似乎与Why must I remove xmlns attribute ... 有关。所以问题是为什么我必须删除 xmlns 属性?我应该使用什么来解析具有 xmlns 属性的 xml?

谢谢

【问题讨论】:

    标签: xml f# xml-namespaces


    【解决方案1】:

    @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")
    

    【讨论】:

    • 这也会稍微快一点;-)。
    【解决方案2】:

    您需要使用它们的命名空间来引用元素:

    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")
    

    【讨论】:

    • 不知道 linq-to-xml 的详细信息,但这可能会稍微快一点:let xnuc = XNamespace.Get("http://api.uclassify.com/1/ResponseSchema").GetName
    • 在 C# 中,通常会执行 var ns = XNamespace.Get(...)doc.Element(ns + "uclassify") 之类的操作,但 F# 不能很好地处理隐式转换,因此可以使用从 string 生成 XName 的函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多