使用 XmlProvider 并更新 xml 给出了错误的命名空间格式
Using XmlProvider and updating xml gives wrong namespace format
我正在使用 XmlProvider,我正在尝试对 xml 文件进行一些更改。
我的问题是写入文件时,命名空间格式发生变化。我尝试了两种方法,第一种方法给出了正确的格式,但我无法将其用于更复杂的更新,比如用新的发票行替换所有发票行。
我怎样才能 update/save 使格式像提供给提供商的 xml 一样?
常用代码:
open System
open System.Xml.Linq
open FSharp.Data
let cbc = XNamespace.Get("urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2")
let cac = XNamespace.Get("urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2")
type Invoice = XmlProvider<"""
<ehf:Invoice xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:ehf="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:ID>5584-2021-2</cbc:ID>
<cac:InvoiceLine>
<cbc:ID>1a</cbc:ID>
<cbc:Note>Note</cbc:Note>
<cac:OrderLineReference>
<cbc:LineID>1</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Item 1</cbc:Name>
</cac:Item>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>1b</cbc:ID>
<cbc:Note>Note</cbc:Note>
<cac:OrderLineReference>
<cbc:LineID>2</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Item 2</cbc:Name>
</cac:Item>
</cac:InvoiceLine>
</ehf:Invoice>
""">
第一种方法(结果如我所愿):
invoice.XElement.SetElementValue(cbc + "ID", "New id")
printfn $"{invoice |> string}"
//<?xml version="1.0" encoding="utf-8"?>
//<ehf:Invoice xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:ehf="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
// <cbc:ID>New id</cbc:ID>
// <cac:InvoiceLine>
// <cbc:ID>1a</cbc:ID>
// <cbc:Note>Note</cbc:Note>
// <cac:OrderLineReference>
// <cbc:LineID>1</cbc:LineID>
// </cac:OrderLineReference>
// <cac:Item>
// <cbc:Name>Item 1</cbc:Name>
// </cac:Item>
// </cac:InvoiceLine>
// <cac:InvoiceLine>
// <cbc:ID>1b</cbc:ID>
// <cbc:Note>Note</cbc:Note>
// <cac:OrderLineReference>
// <cbc:LineID>2</cbc:LineID>
// </cac:OrderLineReference>
// <cac:Item>
// <cbc:Name>Item 2</cbc:Name>
// </cac:Item>
// </cac:InvoiceLine>
//</ehf:Invoice>
第二种方法(给我错误的命名空间格式):
let line = invoice.InvoiceLines.[0]
let newLine = Invoice.InvoiceLine(
"New id",
line.Note,
line.OrderLineReference,
line.Item
)
let changedInvoice = Invoice.Invoice(
invoice.Id,
[|newLine|]
)
printfn $"{changedInvoice |> string}"
//<?xml version="1.0" encoding="utf-8"?>
//<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
// <ID xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">New id</ID>
// <InvoiceLine xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
// <ID xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">New id</ID>
// <Note xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">Note</Note>
// <OrderLineReference>
// <LineID xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">1</LineID>
// </OrderLineReference>
// <Item>
// <Name xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">Item 1</Name>
// </Item>
// </InvoiceLine>
//</Invoice>
问题是新创建的更改发票没有原始文档中的顶级 xmlns
属性并定义命名空间前缀。您可以通过在创建新的 changedInvoice
:
后添加这些内容来解决此问题
let cbc = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
let cac = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
let ext = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
let ehf = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "cbc", cbc)
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "cac", cac)
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "ext", ext)
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "ehf", ehf)
changedInvoice.XElement.ToString()
或者更简单的方法是从原始发票中复制这些内容:
for a in invoice.XElement.Attributes() do
changedInvoice.XElement.SetAttributeValue(a.Name, a.Value)
changedInvoice.XElement.ToString()
我正在使用 XmlProvider,我正在尝试对 xml 文件进行一些更改。
我的问题是写入文件时,命名空间格式发生变化。我尝试了两种方法,第一种方法给出了正确的格式,但我无法将其用于更复杂的更新,比如用新的发票行替换所有发票行。
我怎样才能 update/save 使格式像提供给提供商的 xml 一样?
常用代码:
open System
open System.Xml.Linq
open FSharp.Data
let cbc = XNamespace.Get("urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2")
let cac = XNamespace.Get("urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2")
type Invoice = XmlProvider<"""
<ehf:Invoice xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:ehf="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:ID>5584-2021-2</cbc:ID>
<cac:InvoiceLine>
<cbc:ID>1a</cbc:ID>
<cbc:Note>Note</cbc:Note>
<cac:OrderLineReference>
<cbc:LineID>1</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Item 1</cbc:Name>
</cac:Item>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>1b</cbc:ID>
<cbc:Note>Note</cbc:Note>
<cac:OrderLineReference>
<cbc:LineID>2</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Item 2</cbc:Name>
</cac:Item>
</cac:InvoiceLine>
</ehf:Invoice>
""">
第一种方法(结果如我所愿):
invoice.XElement.SetElementValue(cbc + "ID", "New id")
printfn $"{invoice |> string}"
//<?xml version="1.0" encoding="utf-8"?>
//<ehf:Invoice xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:ehf="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
// <cbc:ID>New id</cbc:ID>
// <cac:InvoiceLine>
// <cbc:ID>1a</cbc:ID>
// <cbc:Note>Note</cbc:Note>
// <cac:OrderLineReference>
// <cbc:LineID>1</cbc:LineID>
// </cac:OrderLineReference>
// <cac:Item>
// <cbc:Name>Item 1</cbc:Name>
// </cac:Item>
// </cac:InvoiceLine>
// <cac:InvoiceLine>
// <cbc:ID>1b</cbc:ID>
// <cbc:Note>Note</cbc:Note>
// <cac:OrderLineReference>
// <cbc:LineID>2</cbc:LineID>
// </cac:OrderLineReference>
// <cac:Item>
// <cbc:Name>Item 2</cbc:Name>
// </cac:Item>
// </cac:InvoiceLine>
//</ehf:Invoice>
第二种方法(给我错误的命名空间格式):
let line = invoice.InvoiceLines.[0]
let newLine = Invoice.InvoiceLine(
"New id",
line.Note,
line.OrderLineReference,
line.Item
)
let changedInvoice = Invoice.Invoice(
invoice.Id,
[|newLine|]
)
printfn $"{changedInvoice |> string}"
//<?xml version="1.0" encoding="utf-8"?>
//<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
// <ID xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">New id</ID>
// <InvoiceLine xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
// <ID xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">New id</ID>
// <Note xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">Note</Note>
// <OrderLineReference>
// <LineID xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">1</LineID>
// </OrderLineReference>
// <Item>
// <Name xmlns="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">Item 1</Name>
// </Item>
// </InvoiceLine>
//</Invoice>
问题是新创建的更改发票没有原始文档中的顶级 xmlns
属性并定义命名空间前缀。您可以通过在创建新的 changedInvoice
:
let cbc = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
let cac = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
let ext = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
let ehf = XNamespace.Get "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "cbc", cbc)
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "cac", cac)
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "ext", ext)
changedInvoice.XElement.SetAttributeValue(XNamespace.Xmlns + "ehf", ehf)
changedInvoice.XElement.ToString()
或者更简单的方法是从原始发票中复制这些内容:
for a in invoice.XElement.Attributes() do
changedInvoice.XElement.SetAttributeValue(a.Name, a.Value)
changedInvoice.XElement.ToString()