Ошибка проверки Xslt для десятичных значений

Я проверяю XML-документ, чтобы проверить общую сумму, подобную этой (извините за стандартный пример):

<book>
    <name>Book 1</name>
    <price>25.30</price>
</book>
<book>
    <name>Book 2</name>
    <price>20.77</price>
</book>
<sum>46.07</sum>

Я загружаю xml и схему проверки и генерирую xml в качестве вывода. Этот вывод содержит информацию о том, какие ошибки произошли:

var xml = new XmlDocument();
xml.Load(@"c:\test.xml")

var myXslTrans = new XslCompiledTransform();
myXslTrans.Load(@"c:\ValidationSchema.xml";);
var xmlDocOut = new XmlDocument();

    using (XmlWriter xmlWriter = xmlDocOut.CreateNavigator().AppendChild())
    {
        myXslTrans.Transform(xml, null, xmlWriter);
    }

По какой-то причине моя проверка всегда терпит неудачу, когда у меня есть десятичные значения.

Я попытался загрузить оба документа с помощью

CultureInfo.InvariantCulture

Я также изменил весь поток, чтобы работать с этой культурой. Может ли это быть связано с кодировкой?


РЕДАКТИРОВАТЬ:

Чтобы уточнить это еще больше:

Проверка проходит успешно, если я запускаю ее в начале кода, но после завершения некоторых гигантских серверных заданий кажется, что какая-то глобальная настройка какого-то типа изменяет какую-то культуру, кодировку или что-то еще, но я не могу понять, где возникает проблема и почему.

Я проверяю электронный счет по этой схеме: http://vefa.difi.no/formatvalidering/resources/validation-xslt/NORWAY-UBL-T10.xsl

Вот мой тестовый счет:

<?xml version="1.0" encoding="utf-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccts="urn:un:unece:uncefact:documentation:2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 UBL-Invoice-2.0.xsd">
  <cbc:UBLVersionID>2.0</cbc:UBLVersionID>
  <cbc:CustomizationID>urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0</cbc:CustomizationID>
  <cbc:ProfileID>urn:www.cenbii.eu:profile:bii05:ver1.0</cbc:ProfileID>
  <cbc:ID>30300109</cbc:ID>
  <cbc:IssueDate>2012-05-09</cbc:IssueDate>
  <cbc:InvoiceTypeCode listID="UN/ECE 1001 Subset" listAgencyID="6">380</cbc:InvoiceTypeCode>
  <cbc:Note languageID="no">Invoice</cbc:Note>
  <cbc:DocumentCurrencyCode listID="ISO 4217" listAgencyID="5">NOK</cbc:DocumentCurrencyCode>
  <cbc:AccountingCost>
  </cbc:AccountingCost>
  <cac:OrderReference>
    <cbc:ID>1234</cbc:ID>
  </cac:OrderReference>
  <cac:ContractDocumentReference>
    <cbc:ID>
    </cbc:ID>
  </cac:ContractDocumentReference>
  <cac:AdditionalDocumentReference>
    <cbc:ID>1 - 30300109 Faktura</cbc:ID>
    <cbc:DocumentType>Commercial invoice</cbc:DocumentType>
    <cac:Attachment>
      <cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf">123123123123</cbc:EmbeddedDocumentBinaryObject>
    </cac:Attachment>
  </cac:AdditionalDocumentReference>
  <cac:AccountingSupplierParty>
    <cac:Party>
      <cac:PartyName>
        <cbc:Name>Demo</cbc:Name>
      </cac:PartyName>
      <cac:PostalAddress>
        <cbc:StreetName>Postbox 3</cbc:StreetName>
        <cbc:CityName>OSLO</cbc:CityName>
        <cbc:PostalZone>0631</cbc:PostalZone>
        <cac:Country>
          <cbc:IdentificationCode listID="ISO 3166" listAgencyID="5">NO</cbc:IdentificationCode>
        </cac:Country>
      </cac:PostalAddress>
      <cac:PartyTaxScheme>
        <cbc:CompanyID>NO910667831MVA</cbc:CompanyID>
        <cac:TaxScheme>
          <cbc:ID>VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:PartyTaxScheme>
      <cac:PartyLegalEntity>
        <cbc:CompanyID schemeID="CVR" schemeAgencyID="ZZZ">910667831</cbc:CompanyID>
      </cac:PartyLegalEntity>
      <cac:Contact>
        <cbc:ID>Per</cbc:ID>
      </cac:Contact>
    </cac:Party>
  </cac:AccountingSupplierParty>
  <cac:AccountingCustomerParty>
    <cac:Party>
      <cac:PartyIdentification>
        <cbc:ID>2072</cbc:ID>
      </cac:PartyIdentification>
      <cac:PartyName>
        <cbc:Name>Wenzel</cbc:Name>
      </cac:PartyName>
      <cac:PostalAddress>
        <cbc:StreetName>Road 4</cbc:StreetName>
        <cbc:CityName>OSLO</cbc:CityName>
        <cbc:PostalZone>0404</cbc:PostalZone>
        <cac:Country>
          <cbc:IdentificationCode listID="ISO 3166" listAgencyID="5">NO</cbc:IdentificationCode>
        </cac:Country>
      </cac:PostalAddress>
      <cac:PartyLegalEntity>
        <cbc:CompanyID schemeAgencyID="ZZZ" schemeID="ZZZ">986532951</cbc:CompanyID>
      </cac:PartyLegalEntity>
      <cac:Contact>
        <cbc:ID>ww</cbc:ID>
      </cac:Contact>
    </cac:Party>
  </cac:AccountingCustomerParty>
  <cac:Delivery>
    <cbc:ActualDeliveryDate>2012-05-09</cbc:ActualDeliveryDate>
    <cac:DeliveryLocation>
      <cac:Address>
        <cbc:StreetName>Road 123</cbc:StreetName>
        <cbc:CityName>OSLO</cbc:CityName>
        <cbc:PostalZone>0404</cbc:PostalZone>
        <cac:Country>
          <cbc:IdentificationCode>NO</cbc:IdentificationCode>
        </cac:Country>
      </cac:Address>
    </cac:DeliveryLocation>
  </cac:Delivery>
  <cac:PaymentMeans>
    <cbc:PaymentMeansCode listID="UN/ECE 4461">31</cbc:PaymentMeansCode>
    <cbc:PaymentDueDate>2012-06-08</cbc:PaymentDueDate>
    <cbc:PaymentID>1020720303001099</cbc:PaymentID>
    <cac:PayeeFinancialAccount>
      <cbc:ID schemeID="BBAN">50841051308</cbc:ID>
    </cac:PayeeFinancialAccount>
  </cac:PaymentMeans>
  <cac:AllowanceCharge>
    <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
    <cbc:AllowanceChargeReason>rebate</cbc:AllowanceChargeReason>
    <cbc:Amount currencyID="NOK">4664.21</cbc:Amount>
    <cac:TaxCategory>
      <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
      <cbc:Percent>25</cbc:Percent>
      <cac:TaxScheme>
        <cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
      </cac:TaxScheme>
    </cac:TaxCategory>
  </cac:AllowanceCharge>
  <cac:AllowanceCharge>
    <cbc:ChargeIndicator>true</cbc:ChargeIndicator>
    <cbc:AllowanceChargeReason>delivery</cbc:AllowanceChargeReason>
    <cbc:Amount currencyID="NOK">2938.45</cbc:Amount>
    <cac:TaxCategory>
      <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
      <cbc:Percent>24.000</cbc:Percent>
      <cac:TaxScheme>
        <cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
      </cac:TaxScheme>
    </cac:TaxCategory>
  </cac:AllowanceCharge>
  <cac:TaxTotal>
    <cbc:TaxAmount currencyID="NOK">11229.08</cbc:TaxAmount>
    <cac:TaxSubtotal>
      <cbc:TaxableAmount currencyID="NOK">44916.30</cbc:TaxableAmount>
      <cbc:TaxAmount currencyID="NOK">11229.08</cbc:TaxAmount>
      <cac:TaxCategory>
        <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
        <cbc:Percent>25</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:TaxCategory>
    </cac:TaxSubtotal>
  </cac:TaxTotal>
  <cac:LegalMonetaryTotal>
    <cbc:LineExtensionAmount currencyID="NOK">46642.06</cbc:LineExtensionAmount>
    <cbc:TaxExclusiveAmount currencyID="NOK">44916.30</cbc:TaxExclusiveAmount>
    <cbc:TaxInclusiveAmount currencyID="NOK">56145.38</cbc:TaxInclusiveAmount>
    <cbc:AllowanceTotalAmount currencyID="NOK">4664.21</cbc:AllowanceTotalAmount>
    <cbc:ChargeTotalAmount currencyID="NOK">2938.45</cbc:ChargeTotalAmount>
    <!--<cbc:PrepaidAmount currencyID=""></cbc:PrepaidAmount>
    <cbc:PayableRoundingAmount currencyID=""></cbc:PayableRoundingAmount>-->
    <cbc:PayableAmount currencyID="NOK">56145.38</cbc:PayableAmount>
  </cac:LegalMonetaryTotal>
  <cac:InvoiceLine>
    <cbc:ID>1</cbc:ID>
    <cbc:InvoicedQuantity unitCode="EA">1.00</cbc:InvoicedQuantity>
    <cbc:LineExtensionAmount currencyID="NOK">12000.00</cbc:LineExtensionAmount>
    <cac:OrderLineReference>
      <cbc:LineID>1</cbc:LineID>
    </cac:OrderLineReference>
    <cac:TaxTotal>
      <cbc:TaxAmount currencyID="NOK">2700.00</cbc:TaxAmount>
    </cac:TaxTotal>
    <cac:Item>
      <cbc:Name>Skrivebord</cbc:Name>
      <cac:SellersItemIdentification>
        <cbc:ID>13000</cbc:ID>
      </cac:SellersItemIdentification>
      <cac:ClassifiedTaxCategory>
        <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
        <cbc:Percent>25.00</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:ClassifiedTaxCategory>
    </cac:Item>
    <cac:Price>
      <cbc:PriceAmount currencyID="NOK">12000</cbc:PriceAmount>
    </cac:Price>
  </cac:InvoiceLine>
  <cac:InvoiceLine>
    <cbc:ID>2</cbc:ID>
    <cbc:InvoicedQuantity unitCode="EA">2.00</cbc:InvoicedQuantity>
    <cbc:LineExtensionAmount currencyID="NOK">30000.00</cbc:LineExtensionAmount>
    <cac:OrderLineReference>
      <cbc:LineID>2</cbc:LineID>
    </cac:OrderLineReference>
    <cac:TaxTotal>
      <cbc:TaxAmount currencyID="NOK">6750.00</cbc:TaxAmount>
    </cac:TaxTotal>
    <cac:Item>
      <cbc:Name>Kontorstol</cbc:Name>
      <cac:SellersItemIdentification>
        <cbc:ID>13002</cbc:ID>
      </cac:SellersItemIdentification>
      <cac:ClassifiedTaxCategory>
        <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
        <cbc:Percent>25.00</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:ClassifiedTaxCategory>
    </cac:Item>
    <cac:Price>
      <cbc:PriceAmount currencyID="NOK">15000</cbc:PriceAmount>
    </cac:Price>
  </cac:InvoiceLine>
  <cac:InvoiceLine>
    <cbc:ID>3</cbc:ID>
    <cbc:InvoicedQuantity unitCode="MTR">14.50</cbc:InvoicedQuantity>
    <cbc:LineExtensionAmount currencyID="NOK">3465.50</cbc:LineExtensionAmount>
    <cac:OrderLineReference>
      <cbc:LineID>3</cbc:LineID>
    </cac:OrderLineReference>
    <cac:TaxTotal>
      <cbc:TaxAmount currencyID="NOK">779.74</cbc:TaxAmount>
    </cac:TaxTotal>
    <cac:Item>
      <cbc:Name>Persienne</cbc:Name>
      <cac:SellersItemIdentification>
        <cbc:ID>13006</cbc:ID>
      </cac:SellersItemIdentification>
      <cac:ClassifiedTaxCategory>
        <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
        <cbc:Percent>25.00</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:ClassifiedTaxCategory>
    </cac:Item>
    <cac:Price>
      <cbc:PriceAmount currencyID="NOK">239</cbc:PriceAmount>
    </cac:Price>
  </cac:InvoiceLine>
  <cac:InvoiceLine>
    <cbc:ID>4</cbc:ID>
    <cbc:InvoicedQuantity unitCode="KGM">62.75</cbc:InvoicedQuantity>
    <cbc:LineExtensionAmount currencyID="NOK">1176.56</cbc:LineExtensionAmount>
    <cac:OrderLineReference>
      <cbc:LineID>4</cbc:LineID>
    </cac:OrderLineReference>
    <cac:TaxTotal>
      <cbc:TaxAmount currencyID="NOK">264.73</cbc:TaxAmount>
    </cac:TaxTotal>
    <cac:Item>
      <cbc:Name>Kaffe</cbc:Name>
      <cac:SellersItemIdentification>
        <cbc:ID>13005</cbc:ID>
      </cac:SellersItemIdentification>
      <cac:ClassifiedTaxCategory>
        <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
        <cbc:Percent>25.00</cbc:Percent>
        <cac:TaxScheme>
          <cbc:ID schemeID="UN/ECE 5153" schemeAgencyID="6">VAT</cbc:ID>
        </cac:TaxScheme>
      </cac:ClassifiedTaxCategory>
    </cac:Item>
    <cac:Price>
      <cbc:PriceAmount currencyID="NOK">18.750</cbc:PriceAmount>
    </cac:Price>
  </cac:InvoiceLine>
</Invoice>

person soberga    schedule 09.05.2012    source источник
comment
Можете ли вы предоставить свою схему проверки? Фон: вы установили правильный тип данных?   -  person Adriano Repetti    schedule 09.05.2012
comment
подробнее в посте :)   -  person soberga    schedule 09.05.2012


Ответы (3)


Похоже, что был основной процесс VB, который испортил мои десятичные числа. Я добавил новый тест, в котором я вычел одно значение (cbc:LineExtensionAmount) с другим (сумма cac:InvoiceLine/cbc:LineExtensionAmount). Это дало мне разницу 0,00000000000001. Мое решение для этого состояло в том, чтобы запускать проверку Xml как отдельный исполняемый файл, пока я не смогу точно локализовать, где возникает моя проблема.

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

namespace test.Transform
{
    class Program
    {
        static void Main(string[] args)
        {

            // Arguments
            // Stylesheet
            // XML-out
            // outpath-xml-path

            if (args.Length != 3)
            {
                Console.WriteLine("parameters Stylesheet XML-out outpath-xml-path");
                return;
            }

            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(args[0]);

            var xml = new XmlDocument();
            xml.Load(args[1]);

            var xmlDocOut = new XmlDocument();

            using (XmlWriter xmlWriter = xmlDocOut.CreateNavigator().AppendChild())
            {
                xslt.Transform(xml, null, xmlWriter);
            }

            xmlDocOut.Save(args[2]);
        }
    }
}

Первый аргумент принимает ValidationSchemaPath, второй Xml-путь, последний выходной путь.

Назовите это так:

    public static XmlDocument TestRun2(string xsltPath, string docPath, IReport _report)
    {

        var tempFile = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
        var x = Process.GetCurrentProcess().MainModule;

        Process p = new Process();
        p.StartInfo.FileName = Path.Combine(Path.GetDirectoryName(x.FileName), "Transform.exe");
        _report.API.WriteLog(p.StartInfo.FileName);
        p.StartInfo.Arguments = string.Format("\"{0}\" \"{1}\" \"{2}\"", xsltPath, docPath, tempFile);
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.Start();

        string output = p.StandardOutput.ReadToEnd();
        p.WaitForExit();

        _report.API.WriteLog("Output from calling Transform.exe");
        _report.API.WriteLog(output);

        if (!File.Exists(tempFile))
        {
            return null;
        }

        var xd = new XmlDocument();
        xd.Load(tempFile);

        return xd;

    }

}
person soberga    schedule 09.05.2012

Хорошо, это не совсем ответ на ваш вопрос, но может решить вашу проблему.

Предполагая, что XML действительно содержит корневой элемент:

var xml = 
    @"<root>
    <book>
        <name>Book 1</name>
        <price>25.30</price>
    </book>
    <book>
        <name>Book 2</name>
        <price>20.77</price>
    </book>
    <sum>46.07</sum>
    </root>";

Затем вы можете использовать LINQ to XML, чтобы делать все, что вам нужно, просто:

var doc = XDocument.Parse(xml);

var sum = doc.Descendants("book").Sum(e => Convert.ToDecimal(e.Element("price").Value));
var total = Convert.ToDecimal(doc.Root.Element("sum").Value);

Console.WriteLine("sum: [{0}] total: [{1}] matched: [{2}]", sum, total, sum == total);
person yamen    schedule 09.05.2012
comment
Но это не проверит его XML, а это то, что он пытался сделать! :) - person Adriano Repetti; 09.05.2012
comment
Конечно, я это понимаю. Но можно обойти всю эту херню. Согласитесь с вашим комментарием к вопросу: просмотрите схему проверки. - person yamen; 09.05.2012
comment
Спасибо, но я боюсь, что не смогу решить эту проблему ;) - person soberga; 09.05.2012

Код XSLT, на который вы ссылаетесь, создается с помощью Schematron. Было бы легче сказать, почему вы получаете ошибки, если бы (а) вы сказали нам, что это за ошибки, и (б) вы показали нам схему Schematron, а не код XSLT, который он генерирует. В коде более 90 вхождений слова "Цена"...

Кроме того, я не вижу (а) как XML книги и XML счета в вашем вопросе связаны друг с другом, или (б) какие у вас есть подсказки, которые заставляют вас думать, что это как-то связано с культурой или кодировкой - что на первый взгляд это кажется довольно невероятной теорией.

person Michael Kay    schedule 09.05.2012
comment
В NORWAY-UBL-T10 есть правило под названием [BIIRULE-T10-R011]. Это один из тестов, который терпит неудачу. Он проверяет общее значение LineExtensionAmount на сумму всех значений InvoiceLine/LineExtensionAmount. - person soberga; 09.05.2012