2012-03-23 17 views
7

एलएक्सएमएल दस्तावेज के अनुसार "डीटीडी को पार्स किए गए दस्तावेज़ के DOCTYPE के आधार पर स्वचालित रूप से पुनर्प्राप्त किया जाता है। आपको केवल एक पार्सर का उपयोग करना है जिसमें डीटीडी सत्यापन सक्षम है।"स्वचालित एक्सएसडी सत्यापन

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

हालांकि, अगर आप एक XML स्कीमा के सामने सत्यापित करना चाहते हैं, आप स्पष्ट रूप से एक संदर्भ के लिए की जरूरत है।

मुझे आश्चर्य है कि यह क्यों है और यह जानना चाहेगा कि कोई लाइब्रेरी या फ़ंक्शन है जो ऐसा कर सकता है। या यह भी एक स्पष्टीकरण है कि इसे स्वयं कैसे किया जाए। समस्या यह है कि एक्सएसडी का संदर्भ देने के कई तरीके हैं और मुझे उन सभी का समर्थन करने की आवश्यकता है।

प्रमाणीकरण समस्या नहीं है। मुद्दा यह है कि स्कीमा को सत्यापित करने के लिए कैसे निर्धारित किया जाए। आदर्श रूप से यह इनलाइन स्कीमा को भी संभाल लेगा।

अद्यतन:

यहाँ एक उदाहरण है।

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> 

मैं निम्नलिखित की तरह कुछ करना चाहते हैं:

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

हम आपको अपने प्रारूपों से निपटने के लिए कैसे नहीं बता सकते हैं। – Marcin

+0

मार्किन, मैं आपकी टिप्पणी को समझ नहीं पा रहा हूं। शायद मैं समझ नहीं पा रहा हूं कि स्कीमा सत्यापन कैसे काम करता है। – Jono

+0

क्या आप इसे विंडोज पर कर रहे हैं? AFAIK माइक्रोसॉफ्ट इनलाइन स्कीमा का समर्थन करने वाला एकमात्र ऐसा है। –

उत्तर

3

मैं एक परियोजना के ऊपर है कि है 100 अलग-अलग स्कीमा और एक्सएमएल पेड़। उन सभी को प्रबंधित करने और उन्हें सत्यापित करने के लिए मैंने कुछ चीजें की हैं।

1) मैंने एक फ़ाइल बनाई है (यानी xmlTrees.py) जहां मैंने प्रत्येक एक्सएमएल और इसके साथ जुड़े संबंधित स्कीमा का एक शब्दकोश बनाया है, और एक्सएमएल पथ। इसने मुझे xml & दोनों एक्सएमएल को प्रमाणित करने के लिए उपयोग की जाने वाली स्कीमा प्राप्त करने के लिए एक ही स्थान प्राप्त करने की अनुमति दी।

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

2) परियोजना में हम समान रूप से के रूप में कई नेमस्पेस (बहुत मुश्किल है प्रबंधित करने के लिए)। तो मैंने जो किया वह फिर से मैंने एक फ़ाइल बनाई जिसमें प्रारूप lxml पसंद में सभी नामस्थान शामिल थे। फिर मेरे परीक्षणों और स्क्रिप्ट में मैं हमेशा नामस्थानों के सुपरसेट को पास करता।

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 

मूल रूप से किसी समारोह इस एक्सएमएल सामग्री और XSD सामग्री भेजने की जरूरत का उपयोग करना चाहता है कि:

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

3) बुनियादी/सामान्य मान्यता के लिए मैं एक बुनियादी कार्य मैं कह सकते हैं बना दी तार के रूप में। यह मुझे सबसे अधिक लचीलापन प्रदान किया। मैंने फिर इस फ़ंक्शन को एक फ़ाइल में रखा जहां मेरे सभी एक्सएमएल सहायक कार्यों थे।

+0

यह मेरे प्रश्न का उत्तर नहीं देता है क्योंकि आप स्कीमा में XML दस्तावेज़ों के स्पष्ट मैपिंग को परिभाषित कर रहे हैं। मेरे प्रश्न का मुद्दा यह है कि कोई मैपिंग का अनुमान कैसे लगा सकता है। – Jono

+0

वास्तव में मैपिंग का अनुमान लगाने का एकमात्र तरीका दुर्भाग्य से कुछ प्रकार के मानचित्रण बनाना है। जब तक स्कीमा की परिभाषा में आप उस यूआरएल को प्राप्त नहीं कर सकते हैं और वास्तव में xsd फ़ाइल को पुनर्प्राप्त कर सकते हैं, या प्रत्येक स्कीमा में आप स्कीमा के स्थान की एक टिप्पणी जोड़ते हैं, जो अभी भी मैपिंग बना रहा है और इसमें शामिल नहीं है, तो आप मूल रूप से नहीं कर सकते हैं। – Jtello

+0

हां, ऊपर मेरे नमूने में मैं एक संदर्भ बनाने के लिए schemaLocation का उपयोग कर रहा हूँ। लेकिन यह इनलाइन को संदर्भित करने का एकमात्र तरीका है। इनलाइन (यानी - रूट नोड के नीचे) करने के कई अन्य तरीके हैं, लेकिन मुझे ऐसी लाइब्रेरी नहीं मिलती है जो इन सभी मामलों को पार्स और मान्य करेगी। – Jono

1

आप स्कीमा खुद निकालें और उन्हें एक रूट स्कीमा में आयात कर सकते हैं:

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, अपने simpletest.xsd targetNamespace याद आ रही है।

<?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> 

उपरोक्त कोड के साथ, आपका उदाहरण दस्तावेज़ इस स्कीमा के विरुद्ध मान्य है।

संबंधित मुद्दे