2012-03-23 33 views
7

lxml belgelerine göre "DTD, ayrıştırılan belgenin DOCTYPE'sine göre otomatik olarak alınır. Tek yapmanız gereken DTD doğrulaması etkinleştirilmiş bir ayrıştırıcı kullanmaktır." Bir XML şemaya göre doğrulanamadı istiyorsanızOtomatik XSD doğrulama

http://lxml.de/validation.html#validation-at-parse-time

Ancak, açık olarak bir başvuru gerekiyor.

Bunun nedenini merak ediyorum ve bunu yapabilecek bir kütüphane veya işlev olup olmadığını bilmek istiyorum. Ya da bunun nasıl gerçekleşeceğine dair bir açıklama bile. Sorun, bir XSD'ye başvurmanın birçok yolu gibi görünüyor ve hepsini desteklemem gerekiyor.

Doğrulama sorun değildir. Sorun, doğrulanacak şemaların nasıl belirleneceğidir. İdeal olarak bu, inline şemaları da ele alacaktır.

Güncelleme: İşte

bir örnektir.

simpletest.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> 
    <xs:element name="name" type="xs:string"/> 
</xs:schema> 

simpletest.xml:

<?xml version="1.0" encoding="UTF-8" ?> 
<name xmlns="http://www.example.org" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.example.org simpletest.xsd">foo</name> 

aşağıdaki gibi bir şey yapmak istiyorum:

>>> parser = etree.XMLParser(xsd_validation=True) 
>>> tree = etree.parse("simpletest.xml", parser) 
+0

Size kendi biçimlerinizle nasıl baş edeceğinizi söyleyemeyiz. – Marcin

+0

Marcin, yorumunuzu anlamıyorum. Belki de şema doğrulamanın nasıl çalıştığını anlamıyorum. – Jono

+0

Windows'da bunu yapıyor musunuz? AFAIK Microsoft, satır içi şemaları destekleyen tek kişidir. –

cevap

3

Oraya içeren bir proje var 100 farklı şema ve xml ağaç. Hepsini yönetmek ve doğrulamak için birkaç şey yaptım.

1) Bir dosya (i.e., xmlTrees.py) oluşturdum ve burada her xml ve onunla ilişkili her şema ve xml yolu için bir sözlük oluşturdum. Bu, xml'yi doğrulamak için kullanılan xml & şemasını elde etmem için tek bir yere sahip olmamı sağladı. Biz yönetmek çok zor eşit sayıda ad alanları (varsa projede

MY_XML = {'url':'/pathToTree/myTree.xml', 'schema':'myXSD.xsd'} 

2)). Bu yüzden tekrar yaptım, lxml beğeni biçimindeki tüm ad alanlarını içeren tek bir dosya oluşturdum. Sonra benim testlerimde ve senaryolarda sadece ad alanlarının üst dizisini geçecektim.

def validateXML(content, schemaContent): 

    try: 
     xmlSchema_doc = etree.parse(schemaContent); 
     xmlSchema = etree.XMLSchema(xmlSchema_doc); 
     xml = etree.parse(StringIO(content)); 
    except: 
     logging.critical("Could not parse schema or content to validate xml"); 
     response['valid'] = False; 
     response['errorlog'] = "Could not parse schema or content to validate xml"; 

    response = {} 
    # Validate the content against the schema. 
    try: 
     xmlSchema.assertValid(xml) 
     response['valid'] = True 
     response['errorlog'] = None 
    except etree.DocumentInvalid, info: 
     response['valid'] = False 
     response['errorlog'] = xmlSchema.error_log 

    return response 
temelde

bu xml içeriğini ve xsd içeriği göndermesi gerekir kullanmak isteyen herhangi bir işlev: temel/genel doğrulama için

ALL_NAMESPACES = { 
    'namespace1': 'http://www.example.org', 
    'namespace2': 'http://www.example2.org' 
} 

3) i diyebiliriz temel işlevi oluşturarak sona erdi dizeler gibi. Bu bana en esneklik sağladı. Sonra bu işlevi tüm xml yardımcı işlevlerimin olduğu bir dosyaya yerleştirdim.

+0

Bu, XML belgelerinin şemalara açık bir şekilde eşlenmesini tanımladığınız için soruma yanıt vermiyor. Benim sorumun noktası, bir kişinin eşlemelerini nasıl çıkarabileceği. – Jono

+0

Eşlemeyi gerçekten çıkarmanın tek yolu, ne yazık ki bir tür haritalama yaratmaktır. Şemaların tanımında bu url'yi elde edemez ve aslında xsd dosyasını alabilir ya da her şemada, şemaya ait bir yorum ekleyerek, hala bir eşleme oluşturmaya ve çıkarım yapmazsınız, temelde yapamazsınız. – Jtello

+0

Evet, yukarıdaki örnekte, başvuru yapmak için schemaLocation kullanıyorum. Ancak bu, satır içi başvurmak için sadece bir yoldur. Bunu satır içi yapmak için başka birçok yol vardır (yani - kök düğümünün altında), ancak tüm bu vakaları ayrıştıracak ve onaylayacak bir kütüphane bulamıyorum. – Jono

1

şemalar kendinizi ayıklamak ve bir kök şema içine alabiliriz:

from lxml import etree 

XSI = "http://www.w3.org/2001/XMLSchema-instance" 
XS = '{http://www.w3.org/2001/XMLSchema}' 


SCHEMA_TEMPLATE = """<?xml version = "1.0" encoding = "UTF-8"?> 
<xs:schema xmlns="http://dummy.libxml2.validator" 
targetNamespace="http://dummy.libxml2.validator" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
version="1.0" 
elementFormDefault="qualified" 
attributeFormDefault="unqualified"> 
</xs:schema>""" 


def validate_XML(xml): 
    """Validate an XML file represented as string. Follow all schemaLocations. 

    :param xml: XML represented as string. 
    :type xml: str 
    """ 
    tree = etree.XML(xml) 
    schema_tree = etree.XML(SCHEMA_TEMPLATE) 
    # Find all unique instances of 'xsi:schemaLocation="<namespace> <path-to-schema.xsd> ..."' 
    schema_locations = set(tree.xpath("//*/@xsi:schemaLocation", namespaces={'xsi': XSI})) 
    for schema_location in schema_locations: 
     # Split namespaces and schema locations ; use strip to remove leading 
     # and trailing whitespace. 
     namespaces_locations = schema_location.strip().split() 
     # Import all found namspace/schema location pairs 
     for namespace, location in zip(*[iter(namespaces_locations)] * 2): 
      xs_import = etree.Element(XS + "import") 
      xs_import.attrib['namespace'] = namespace 
      xs_import.attrib['schemaLocation'] = location 
      schema_tree.append(xs_import) 
    # Contstruct the schema 
    schema = etree.XMLSchema(schema_tree) 
    # Validate! 
    schema.assertValid(tree) 

BTW, sizin simpletest.xsd targetNamespace eksik.

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://www.example.org" elementFormDefault="qualified"> 
    <xs:element name="name" type="xs:string"/> 
</xs:schema> 

Yukarıdaki kodla, örnek belgeniz bu şemaya göre doğrulanır.