带有命名空间和前缀的 Json 到 XML

Posted

技术标签:

【中文标题】带有命名空间和前缀的 Json 到 XML【英文标题】:Json to XML with namespaces and prefix 【发布时间】:2021-07-27 17:40:16 【问题描述】:

我有一个 json,我想为电子发票创建特定的 XML 格式。


   "invoice": 
      "issuer": 
         "vatNumber": "888888888",
         "country": "GR",
         "branch": "1"
      ,
      "counterpart": 
         "vatNumber": "999999999",
         "country": "GR",
         "branch": "0",
         "address": 
            "postalCode": "12345",
            "city": "TEST"
         
      ,
      "invoiceHeader": 
         "series": "A",
         "aa": "101",
         "issueDate": "2021-04-27",
         "invoiceType": "1.1",
         "currency": "EUR"
      ,
      "paymentMethods": 
         "paymentMethodDetails": 
            "type": "3",
            "amount": "1760.00",
            "paymentMethodInfo": "Payment Method Info..."
         
      ,
      "invoiceDetails": [
         
            "lineNumber": "1",
            "netValue": "1000.00",
            "vatCategory": "1",
            "vatAmount": "240.00",
            "discountOption": "true",
            "incomeClassification": 
               "classificationType": "E3_561_001",
               "classificationCategory": "category1_2",
               "amount": "1000.00"
            
         ,
         
            "lineNumber": "2",
            "netValue": "500.00",
            "vatCategory": "1",
            "vatAmount": "120.00",
            "discountOption": "true",
            "incomeClassification": 
               "classificationType": "E3_561_001",
               "classificationCategory": "category1_3",
               "amount": "500.00"
            
         
      ],
      "taxesTotals": 
         "taxes": 
            "taxType": "1",
            "taxCategory": "2",
            "underlyingValue": "500.00",
            "taxAmount": "100.00"
         
      ,
      "invoiceSummary": 
         "totalNetValue": "1500.00",
         "totalVatAmount": "360.00",
         "totalWithheldAmount": "100.00",
         "totalFeesAmount": "0.00",
         "totalStampDutyAmount": "0.00",
         "totalOtherTaxesAmount": "0.00",
         "totalDeductionsAmount": "0.00",
         "totalGrossValue": "1760.00",
         "incomeClassification": [
            
               "classificationType": "E3_561_001",
               "classificationCategory": "category1_2",
               "amount": "1000.00"
            ,
            
               "classificationType": "E3_561_001",
               "classificationCategory": "category1_3",
               "amount": "500.00"
            
         ]
      
   

https://www.aade.gr/sites/default/files/2020-09/SampleXML_1.1_taxes_per_invoice%20%28%CE%A4%CE%99%CE%9C-%CE%A0%CE%A9%CE%9B%CE%97%CE%A3%CE%97%CE%A3%29.xml

您能帮我找到实现这一目标的最佳解决方案吗?我正在使用 .net core 3.1

我现在的问题是命名空间和前缀

<InvoicesDoc xmlns="http://www.aade.gr/myDATA/invoice/v1.0"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.aade.gr/myDATA/invoice/v1.0/InvoicesDoc-v0.6.xsd"   
        xmlns:icls="https://www.aade.gr/myDATA/incomeClassificaton/v1.0"
        xmlns:ecls="https://www.aade.gr/myDATA/expensesClassificaton/v1.0">

...

<incomeClassification>
                <icls:classificationType>E3_561_001</icls:classificationType>
                <icls:classificationCategory>category1_2</icls:classificationCategory>
                <icls:amount>1000.00</icls:amount>               
</incomeClassification>

【问题讨论】:

【参考方案1】:

命名空间很棘手。所以我喜欢解析字符串,这比在代码中尝试更容易。这是一个使用 xml linq 的示例:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication

    class Program
    
        const string FILENAME = @"c:\temp\test.xml";
         static void Main(string[] args)
        
             string ident = 
                 "<InvoicesDoc xmlns=\"http://www.aade.gr/myDATA/invoice/v1.0\"" +  
                 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
                 " xmlns:icls=\"https://www.aade.gr/myDATA/incomeClassificaton/v1.0\"" +
                 " xmlns:ecls=\"https://www.aade.gr/myDATA/expensesClassificaton/v1.0\"" +
                 " xsi:schemaLocation=\"http://www.aade.gr/myDATA/invoice/v1.0/InvoicesDoc-v0.6.xsd\">" +
                 "</InvoicesDoc>";

             XDocument doc = XDocument.Parse(ident);
             XElement invoicesDoc = doc.Root;
             XNamespace ns = invoicesDoc.GetDefaultNamespace();
             XNamespace nsIcls = invoicesDoc.GetNamespaceOfPrefix("icls");
             XNamespace nsEcls = invoicesDoc.GetNamespaceOfPrefix("ecls");
             XElement invoice = new XElement(ns + "invoice");
             invoicesDoc.Add(invoice);

             XElement incomeClassification = new XElement(ns + "incomeClassification", new object[] 
                 new XElement(nsIcls + "classificationType", "E3_561_001"),
                 new XElement(nsIcls + "classificationCategory", "category1_2"),
                 new XElement(nsIcls + "amount", 1000.00),
             );
             invoice.Add(incomeClassification);

        
    
  

【讨论】:

谢谢。我会试试的!【参考方案2】:

您可以按照以下思路使用 XSLT 3.0:

    <xsl:template name="xsl:initial-template">
      <xsl:variable name="in" select="json-doc('input-json.json')"/>
      <InvoicesDoc xmlns="http://www.aade.gr/myDATA/invoice/v1.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.aade.gr/myDATA/invoice/v1.0/InvoicesDoc-v0.6.xsd"   
            xmlns:icls="https://www.aade.gr/myDATA/incomeClassificaton/v1.0"
            xmlns:ecls="https://www.aade.gr/myDATA/expensesClassificaton/v1.0">
         <xsl:for-each select="$in?invoices?invoiceDetails?*">
           <incomeClassification>
             <icls:classificationType>?incomeClassification?classificationType</icls:classificationType>                           
             <icls:classificationCategory>?incomeClassification?classificationCategory</icls:classificationCategory>
             <icls:amount>?incomeClassification?amount</icls:amount>               
           </incomeClassification>
         </xsl:for-each>
      </InvoicesDoc>
    </xsl:template>
     

【讨论】:

请您提供有关带有 net core 3.1 的 xslt 3 的更多信息吗?我没有再用过。 目前有两种 XSLT 3.0 处理器可用:Altova 和 Saxon。 Saxon(我的产品)尚未在 .net 核心上运行(我们正在努力)。我不能代表阿尔托娃。提供有关某项技术的介绍性信息超出了 SO 答案的范围:如果您寻找它,周围有很多信息,而且您总是可以就特定点提出问题。

以上是关于带有命名空间和前缀的 Json 到 XML的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 DOM 解析器读取带有命名空间前缀的 xml

使用命名空间前缀更新 XML 文件

XSLT - 删除前缀命名空间特定节点 XML

带有命名空间前缀的 TagSoup 属性

在java中将带有命名空间的xml转换为json

Excel 到 XML 命名空间前缀自定义