XML, blokowanie wbudowanych XSD podczas walidacji

0

Witajcie
Mam plik XML, który waliduje w sumie 5 plikami XSD, normalnie dzieje się to poprzez wbudowane pliki XSD, tzn XML ma odnośniki do plików XSD, które są gdzieś w internecie. Chce aby walidacja odbywała się bez dostępu do internetu, wymagane pliki XSD mam, ale tu pojawia się problem. Jeśli komputer posiada dostęp do internetu to i tak pobiera pliki XSD wskazane przez plik XML i występuje konflikt, ponieważ ja te pliki już podałem do schematu walidacji i dwa pliki próbują stworzyć rodzaj zmiennej o takiej samej nazwie. Jeśli program nie ma dostępu do internetu to wszystko śmiga. No więc nasuwa się pytanie, jak zablokować pobieranie tych plików?

Edit: a no i edycja wejściowego pliku xml nie wchodzi w gre, ponieważ musza one mieć ściśle określoną strukturę.

                XmlReaderSettings settings = new XmlReaderSettings();
                settings.Schemas.Add(schema);
                settings.ValidationType = ValidationType.Schema;

                stream = new FileStream(_nazwaPliku, FileMode.Open);            
              
                reader = XmlReader.Create(stream, settings);   // blad wyrzuca już na tej linijce
                XmlDocument document = new XmlDocument();
                document.Load(reader);

                ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler)
                document.Validate(eventHandler);
0

Rozumiem, ze xródlowy xml ma schemalocation i stąd są pobierane?

0

Tak, to te same pliki ktore ja podaje wczesniej "na sztywno" w c#. A zeby nie bylo tak prosto to jest to w sumie 5 plikow XSD i wszsystkie odnoszą sie do folderu, w ktorym znajdują sie 4 z nich, plik XML rowniez odnosi sie do jednego pliku XSD i folderu, w ktorym znajdują sie pozostale 4.

0

To jest jakiś bełkot... co to znaczy, że xsd odnosi się do folderu? Co to znaczy że xml odosi się do folderu? Zacznij używac poprawnego nazewnictwa lub pokaż xml-a bo inaczej nic nie zrobimy.
Czy rozmawiamy o schema location czy o imporcie?

0
<Invoice xmlns:udt="tu-jest-adres-http-do-folderu-z-4-plikami-xsd">
<!--> tresc pliku xml <!-->
</Invoice>

Nie mam teraz tego pliku przed sobą, dlatego pisze z pamięci, tak to wygląda. Jest plik xml i 5 plikow xsd. Wszytkie te pliki mają odwolania do tego folderu w ten sposob, a sam plik xml oprocz tego ma odwolanie do ostatniego pliku xsd. Wszystkie te pliki mam rowniez na dysku i chce aby bez ingerencji w plik xml dalo sie przeprowadzic walidacje pliku xml bez robienia zapytań do wyzej wymienionego adresu http. Na obecna chwile to dziala pod warunkiem ze komputer nie ma fizycznego dostepu do internetu i nie jest w stanie uzysakac odpowiedzi z serwera, ale jesli internet sie pojawia to "z automatu" pobiera schemy, czyli pliki xsd, z tego co rozumiem dlatego ze xml sie do nich odwoluje no i pojawiają sie bledy bo wczytywane z internetu schemy tworzą takie same, tzn o tej samej nazwie, wzory zmiennych, pól czy klas (?? nie wiem jak to sie nazywa, xml'em zajmuje sie tylko przy okazji) jak schemy ktore podaje z dysku, bo to w koncu te same pliki. Chce to zablokowac zeby walidacja zawsze dzialala bez odwolan do zewnetrznych serwerow bo mamy z tym problem.

0

To co ty nazywasz folderem to jest w xml-u namespace, link do "ostatniego" xsd to prawdopodobnie wskazanie schemaLocations, więc trzeba przeanalaizować schematy xsd i pobrać lokalnie wszystkie.

Tu masz zbliżony problem
https://stackoverflow.com/questions/7982275/how-can-i-resolve-the-schemalocation-attribute-of-an-xsd-when-all-of-my-xsds

Ale to jest strzelanie w ciemno bo bez xml-a ciężko powiedzieć więcej, bo twój opis tego nie ułatwia...

0

tak wyglada pierwsza linijka xml, dalej jest juz tresc dokumentu

<tns:JPK xmlns:tns="http://jpk.mf.gov.pl/wzor/2017/11/13/1113/" xmlns:etd="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2016/01/25/eD/DefinicjeTypy/">

wszystkie pliki schema mam na dysku, gdybym czegos nie miał to walidacja by nie dzialala bez dostępu do internetu a działa.

wyrzuca dokładnie taki blad

Element simpleType 'http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2016/01/25/eD/DefinicjeTypy/:TZnakowy' został już zadeklarowany.

TZnakowy to jest typ zmiennej zadeklarowany w jednym z plików schema, ja go mam na dysku i wczytuje go przed walidacją do schemy. Później program "z automatu" pobiera schemy wskazywane przez plik xml i moim zdaniem stad ten błąd, ponieważ typ TZnakowy i wszystkie inne chcą się deklarować ponownie a one już istnieją.

JPK VAT, wersja 3, schema 1-1

0

No to pokolei, do sprawdzenia jpk_vat potrzebujemy 5 plikow xsd:

Dla przestrzeni nazw: http://jpk.mf.gov.pl/wzor/2017/11/13/1113/::

  1. Schemat_JPK_VAT(3)_v1-1.xsd

Dla przestrzeni nazw http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2016/01/25/eD/DefinicjeTypy/:
2. StrukturyDanych_v4-0E.xsd
3. ElementarneTypyDanych_v4-0E.xsd
4. KodyUrzedowSkarbowych_v4-0E.xsd
5. KodyKrajow_v4-1E.xsd

i teraz tak:

  1. plik Schemat_JPK_VAT(3)_v1-1.xsd importuje StrukturyDanych_v4-0E.xsd
  2. Plik StrukturyDanych_v4-0E.xsd dołącza (include) ElementarneTypyDanych_v4-0E.xsd
  3. Plik ElementarneTypyDanych_v4-0E.xsd includuje KodyUrzedowSkarbowych_v4-0E.xsd i KodyKrajow_v4-1E.xsd

Czyli dodając Schemat_JPK_VAT(3)_v1-1.xsd w kolekcji schemaset pojawią się wszystkie pliki i każde kolejne dodanie spowoduje błąd z duplikacją nazw.

Czyli najproście napisać własnego XmlResolver który zamiast pobierać z netu pobierze lokalnie z dysku.
Załóżmy, że wszystko masz w katalogu c:\roboczy\xml\

I chcesz sprawdzić takiego błednego xml-a:

<?xml version="1.0" encoding="UTF-8"?>
<JPK xmlns="http://jpk.mf.gov.pl/wzor/2017/11/13/1113/" xmlns:etd="http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2016/01/25/eD/DefinicjeTypy/">
	<Naglowek>
		<KodFormularza kodSystemowy="JPK_VAT (3)" wersjaSchemy="1-0">JPK_VAT</KodFormularza>
		<WariantFormularza>3</WariantFormularza>
		<CelZlozenia>1</CelZlozenia>
		<DataWytworzeniaJPK>2019-06-14T12:25:07</DataWytworzeniaJPK>
		<DataOd>2019-06-01</DataOd>
		<DataDo>2019-06-30</DataDo>
		<NazwaSystemu>program</NazwaSystemu>
	</Naglowek>
	<Podmiot1>
		<NIP>błędny nip</NIP>
		<PelnaNazwa>Pełna nazwa firmy</PelnaNazwa>
	</Podmiot1>
</JPK>

Kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.IO;
namespace ConsoleApp1
{
    class Program
    {
        internal class XUrlResolver : XmlUrlResolver
        {
           

            public override Uri ResolveUri(Uri baseUri, string relativeUri)
            {
                return base.ResolveUri(baseUri, relativeUri);
            }
            public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
            {
                 if (absoluteUri.Scheme == "http")
                {

                    string xsd = absoluteUri.Segments.Last();
                    Console.WriteLine(xsd);
                    return new MemoryStream(File.ReadAllBytes(@"C:\Roboczy\xml\" + xsd));
                }

                return base.GetEntity(absoluteUri, role, ofObjectToReturn);
            
                
            }
        }
        static void Main(string[] args)
        {
            XmlReaderSettings xmlSettings = new XmlReaderSettings();
            xmlSettings.ValidationType = ValidationType.Schema;
            xmlSettings.Schemas.XmlResolver = new XUrlResolver();
            xmlSettings.Schemas.Add(null, @"C:\Roboczy\xml\Schemat_JPK_VAT(3)_v1-1.xsd");
            xmlSettings.Schemas.Compile();

            xmlSettings.ValidationEventHandler += new ValidationEventHandler(xmlSettingsValidationEventHandler);
            var streamXML = new FileStream(@"c:\roboczy\xml\jpk_vat.xml", FileMode.Open);
            XmlReader xmlJPK = XmlReader.Create(streamXML, xmlSettings);

           
            while (xmlJPK.Read()) ;
            Console.Write("Koniec");
        }
        static void xmlSettingsValidationEventHandler(object sender, ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Warning)
            {
                Console.Write("WARNING: ");
                Console.WriteLine(e.Message);
            }
            else if (e.Severity == XmlSeverityType.Error)
            {
                Console.Write("ERROR: ");
                Console.WriteLine(e.Message);
            }
        }
    }
}

Nie jest to jakoś specjalnie dopracowane, ale pokazuje ci tylko droge do celu...

wynik

StrukturyDanych_v4-0E.xsd
ElementarneTypyDanych_v4-0E.xsd
KodyUrzedowSkarbowych_v4-0E.xsd
KodyKrajow_v4-1E.xsd
ERROR: Wartość atrybutu 'wersjaSchemy' nie jest równa jego ustalonej wartości.
ERROR: Element 'http://jpk.mf.gov.pl/wzor/2017/11/13/1113/:NIP' jest nieprawidłowy. Wartość 'błędny nip' jest nieprawidłowa przy uwzględnieniu jego typu danych 'http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2016/01/25/eD/DefinicjeTypy/:TNrNIP' - Błąd ograniczenia elementu Pattern..
Koniec

druga ściezka to połaczenie plików xsd odpowiedzialnych za http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2016/01/25/eD/DefinicjeTypy/ w jeden plik, wyrzucenie importu z Schemat_JPK_VAT(3)_v1-1.xsd i załadowanie tych dwóch plikow lokalnie, wtedy nic nie bedzie brane z internetu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1