Erlang 21 - 1. xmerl

1 xmerl




erlang

1 xmerl

१.१ परिचय

विशेषताएं

Xmerl XML पार्सर XML 1.0 मानक के अनुसार XML दस्तावेजों को पार्स करने में सक्षम है। डिफ़ॉल्ट रूप से यह अच्छी तरह से गठित पार्सिंग करता है, (सिंटैक्स चेक और अच्छी तरह से गठित बाधाओं की जांच)। वैकल्पिक रूप से एक भी एक वैध पार्सर के रूप में xmerl का उपयोग कर सकते हैं, (संदर्भित DTD के अनुसार मान्य करें और बाधाओं को मान्य करें)। उदाहरण के लिए xmerl_xs मॉड्यूल के द्वारा पार्स किए गए परिणाम को अन्य प्रारूपों, जैसे टेक्स्ट, HTML, XML आदि में बदलना संभव है।

अवलोकन

यह दस्तावेज़ XML का परिचय नहीं देता है। ऐसी बहुत सी पुस्तकें उपलब्ध हैं जो विभिन्न विचारों से XML का वर्णन करती हैं। www.W3.org साइट पर आपको XML 1.0 specification और अन्य संबंधित ऐनक मिलेंगे। एक साइट थी कि आप XML पर ट्यूटोरियल पा सकते हैं और संबंधित चश्मा ZVON.org

हालाँकि, यहाँ आपको कुछ उदाहरण मिलेंगे कि कैसे उपयोग करें और क्या आप xmerl का उपयोग कर सकते हैं। उपयोगकर्ता इंटरफ़ेस का विस्तृत विवरण संदर्भ पुस्तिका में पाया जा सकता है।

Xmerl में दो ज्ञात कमियाँ हैं:

  • यह एक URL संदर्भ द्वारा इंटरनेट पर बाहरी संस्थाओं को पुनर्प्राप्त नहीं कर सकता है, केवल स्थानीय फाइल सिस्टम में संसाधन।
  • xmerl यूनिकोड एनकोडेड डेटा को पार्स कर सकता है। लेकिन, यह टैग नामों, विशेषता नामों और अन्य मार्क-अप नामों पर विफल रहता है जो यूनिकोड वर्णों को एन्कोडेड हैं जो ASCII पर मैपिंग नहीं करते हैं।

XML दस्तावेज़ पार्स करने से आपको एक रिकॉर्ड मिलेगा, जो दस्तावेज़ की संरचना को प्रदर्शित करता है, रिटर्न वैल्यू के रूप में। रिकॉर्ड में दस्तावेज़ का डेटा भी होता है। xmerl उदाहरण के लिए निम्नलिखित परिदृश्यों में उपयोग करना सुविधाजनक है:

आपको XML दस्तावेज़ों से डेटा पुनर्प्राप्त करने की आवश्यकता है। आपका Erlang सॉफ़्टवेयर XML दस्तावेज़ की जानकारी को पार्सिंग द्वारा प्राप्त डेटा संरचना से डेटा निकालकर संभाल सकता है।

यह भी संभव है कि एक्सएमएल के साथ पार्स किए गए एक्सएमएल की आगे की प्रक्रिया हो। यदि आप उदाहरण के लिए HTML, पाठ या अन्य XML प्रारूप के लिए XML दस्तावेज़ का प्रारूप बदलना चाहते हैं तो आप इसे बदल सकते हैं। Xmerl में ऐसे परिवर्तनों के लिए समर्थन है।

कोई भी XML के लिए मनमाना डेटा परिवर्तित कर सकता है। इसलिए, उदाहरण के लिए, इसे मनुष्यों द्वारा पठनीय बनाना आसान है। इस स्थिति में आप पहले अपने डेटा से xmerl डेटा स्ट्रक्चर्स बनाते हैं, फिर इसे XML में बदलते हैं।

आप नीचे दिए गए उपयोग के इन तीन उदाहरणों के उदाहरण पा सकते हैं।

1.2 xmerl उपयोगकर्ता इंटरफ़ेस डेटा संरचना

पार्स किए गए डेटा को बचाने के लिए xmerl द्वारा उपयोग किए गए निम्नलिखित रिकॉर्ड xmerl.hrl में परिभाषित किए xmerl.hrl

एक सफल पार्सिंग का परिणाम एक टपल {DataStructure,M} M एक्सएमएल उत्पादन विविध है, जो दस्तावेज के तत्व के बाद आने वाला मार्क-अप है। इसे "जैसा है" वैसा ही लौटाया जाता है। DataStructure एक xmlElement रिकॉर्ड है, जिसमें अन्य लोगों के name , parents , attributes और content जैसे फ़ील्ड हैं:

#xmlElement{name=Name,
            ...
            parents=Parents,
            ...
            attributes=Attrs,
            content=Content,
            ...}    

तत्व का name फ़ील्ड में पाया जाता है। parents फ़ील्ड में सहेजे गए मूल तत्वों के नाम हैं। माता-पिता tuples की एक सूची है जहाँ प्रत्येक tuple में पहला तत्व मूल तत्व का नाम है। सूची रिवर्स ऑर्डर में है।

रिकॉर्ड xmlAttribute फ़ील्ड name और value में एक विशेषता का नाम और मान रखता है। किसी तत्व के सभी गुण xmlEtt रिकॉर्ड के फ़ील्ड attributes में xmlAttribute की एक सूची है।

शीर्ष तत्व की content फ़ील्ड रिकॉर्ड की एक सूची है जो दस्तावेज़ की संरचना और डेटा दिखाती है। यदि यह एक साधारण दस्तावेज है जैसे:

<?xml version="1.0"?>
<dog>
Grand Danois
</dog>    

परिणाम होगा:

#xmlElement{name = dog,
            ...
            parents = [],
            ...
            attributes = [],
            content = [{xmlText,[{dog,1}],1,[],"\
Grand Danois\
",text}],
            ...
            }    

जहां शीर्ष तत्व की सामग्री है: [{xmlText,[{dog,1}],1,[],"\ Grand Danois\ ",text}] । टेक्स्ट को xmlText रिकॉर्ड में वापस कर दिया जाएगा। हालांकि, आमतौर पर दस्तावेज़ अधिक जटिल होते हैं, और शीर्ष तत्व की सामग्री उस मामले में xmlElement रिकॉर्ड के साथ एक नेस्टेड संरचना होगी जो बदले में जटिल सामग्री हो सकती है। यह सब XML दस्तावेज़ की संरचना को दर्शाता है।

स्पेस-अप, tab और line feed रूप में मार्क-अप के बीच के अंतरिक्ष वर्णों को सामान्यीकृत किया जाता है और xmlText रिकॉर्ड के रूप में वापस किया जाता है।

त्रुटियाँ

एक असफल पार्स के परिणामस्वरूप एक त्रुटि होती है, जो टपल {error,Reason} या एक निकास हो सकती है: {'EXIT',Reason} । एक्सएमएल 1.0 मानक के अनुसार fatal error और error स्थिति है। एक घातक पार्सर द्वारा घातक त्रुटियों का पता लगाया जाना चाहिए, जबकि एक त्रुटि का पता लगाया जा सकता है। त्रुटियों की दोनों श्रेणियों को xmerl के इस संस्करण द्वारा घातक त्रुटियों के रूप में सूचित किया जाता है, सबसे अधिक बार बाहर निकलने के रूप में।

1.3 आरंभ करना

निम्नलिखित उदाहरणों में हम XML फ़ाइल "motorcycles.xml" और संबंधित DTD "motorcycles.dtd" का उपयोग करते हैं। मोटरसाइकिल। xml जैसा दिखता है:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE motorcycles SYSTEM "motorcycles.dtd">
<motorcycles>
  <bike year="2000" color="black">
    <name>
      <manufacturer>Suzuki</manufacturer>
      <brandName>Suzuki VL 1500</brandName>
      <additionalName>Intruder</additionalName>
    </name>
    <engine>V-engine, 2-cylinders, 1500 cc</engine>
    <kind>custom</kind>
    <drive>cardan</drive>
    <accessories>Sissy bar, luggage carrier,V&amp;H exhaust pipes</accessories>
  </bike>
  <date>2004.08.25</date>
  <bike year="1983" color="read pearl">
    <name>
      <manufacturer>Yamaha</manufacturer>
      <brandName>XJ 400</brandName>
    </name>
    <engine>4 cylinder, 400 cc</engine>
    <kind>alround</kind>
    <drive>chain</drive>
    <comment>Good shape!</comment>
  </bike>
</motorcycles>

और motorcycles.dtd ऐसा लगता है:

<?xml version="1.0" encoding="utf-8" ?>
<!ELEMENT motorcycles (bike,date?)+ >
<!ELEMENT bike        (name,engine,kind,drive, accessories?,comment?) >
<!ELEMENT name        (manufacturer,brandName,additionalName?) >
<!ELEMENT manufacturer       (#PCDATA)>
<!ELEMENT brandName         (#PCDATA)>
<!ELEMENT additionalName    (#PCDATA)>
<!ELEMENT engine             (#PCDATA)>
<!ELEMENT kind               (#PCDATA)>
<!ELEMENT drive              (#PCDATA)>
<!ELEMENT comment            (#PCDATA)>
<!ELEMENT accessories        (#PCDATA)>

<!-- Date of the format yyyy.mm.dd -->
<!ELEMENT date              (#PCDATA)>
<!ATTLIST  bike year NMTOKEN #REQUIRED
                color NMTOKENS #REQUIRED
                condition (useless | bad | serviceable | moderate | good |
                           excellent | new | outstanding) "excellent" >

यदि आप XML फ़ाइल motorcycles.xml को पार्स करना चाहते हैं, तो आप इसे Erlang शेल में चलाते हैं जैसे:

3> {ParsResult,Misc}=xmerl_scan:file("motorcycles.xml"). 
{{xmlElement,motorcycles,
             motorcycles,
             [],
             {xmlNamespace,[],[]},
             [],
             1,
             [],
             [{xmlText,[{motorcycles,1}],1,[],"\
  ",text},
              {xmlElement,bike,
                          bike,
                          [],
                          {xmlNamespace,[],[]},
                          [{motorcycles,1}],
                          2,
                          [{xmlAttribute,year,[],[],[],[]|...},
                           {xmlAttribute,color,[],[],[]|...}],
                          [{xmlText,[{bike,2},{motorcycles|...}],
                                    1,
                                    []|...},
                           {xmlElement,name,name,[]|...},
                           {xmlText,[{...}|...],3|...},
                           {xmlElement,engine|...},
                           {xmlText|...},
                           {...}|...],
                          [],
                          ".",
                          undeclared},
              ...
              ],
             [],
             ".",
             undeclared},
 []}
4>     

यदि आप इसके बजाय XML डॉक्टर को एक स्ट्रिंग के रूप में प्राप्त करते हैं तो आप इसे xmerl_scan:string/1 द्वारा पार्स कर सकते हैं। फ़ाइल / 2 और स्ट्रिंग / 2 दोनों मौजूद हैं जहां दूसरा तर्क पार्सर के विकल्पों की एक सूची है, reference manual

1.4 उदाहरण: एक्सएमएल कंटेंट से डेटा निकालना

इस उदाहरण में उस स्थिति पर विचार करें जहां आप XML फ़ाइल में किसी विशेष डेटा की जांच करना चाहते हैं। उदाहरण के लिए, आप यह देखना चाहते हैं कि प्रत्येक मोटरसाइकिल कितने समय तक रिकॉर्ड की गई है।

DTD पर एक नज़र डालें और निरीक्षण करें कि एक XML दस्तावेज़ की संरचना जो इस DTD के अनुरूप है, उसमें एक मोटरसाइकिल तत्व (मूल तत्व) होना चाहिए। मोटरसाइकिल तत्व में कम से कम एक बाइक तत्व होना चाहिए। प्रत्येक बाइक तत्व के बाद यह एक तिथि तत्व हो सकता है। दिनांक तत्व की सामग्री #PCDATA (पार्स कैरेक्टर डेटा) है, अर्थात कच्चा पाठ। ध्यान रखें कि यदि #PCDATA में "<" या "&" अक्षर होना चाहिए, तो उसे "&lt;" लिखा जाना चाहिए "&lt;" और "&amp;" क्रमशः। इसके अलावा अन्य वर्ण संस्थाएँ HTML और SGML में भी मौजूद हैं।

यदि आप xmerl_scan:file('motorcycles.xml',[{validation,true}]) में सत्यापन के साथ XML फ़ाइल को सफलतापूर्वक पार्स करते हैं xmerl_scan:file('motorcycles.xml',[{validation,true}]) तो आप जानते हैं कि XML दस्तावेज़ मान्य है और DTD के अनुसार संरचना है।

इस प्रकार, अनुमत संरचना को जानना एक प्रोग्राम लिखना आसान है जो डेटा संरचना का पता लगाता है और नाम तिथि के साथ xmlElements रिकॉर्ड में जानकारी चुनता है।

उस सफेद स्थान का निरीक्षण करें: प्रत्येक स्थान, टैब या लाइन फ़ीड, xmlText रिकॉर्ड में मार्क-अप परिणामों के बीच।

1.5 उदाहरण: एक्सएमएल आउट ऑफ़ आर्बिटवर्ल्ड डेटा बनाएँ

इस कार्य के लिए जाने के लिए एक से अधिक तरीके हैं। "ब्रूट फोर्स" विधि आपके द्वारा आवश्यक रिकॉर्ड बनाने और उपयुक्त तत्व की सामग्री और विशेषता फ़ील्ड में अपना डेटा खिलाने के लिए है।

"सरल-स्वरूप" प्रारूप द्वारा xmerl में इसके लिए समर्थन है। आप अपने डेटा को एक साधारण-फॉर्म डेटा संरचना में रख सकते हैं और इसे xmerl:export_simple(Content,Callback,RootAttributes) में फ़ीड कर xmerl:export_simple(Content,Callback,RootAttributes) । सामग्री xmlElement और xmlText के रूप में सरल-प्रपत्र और xmerl रिकॉर्ड का मिश्रण हो सकती है।

प्रकार हैं:

  • सामग्री = [तत्व]
  • कॉलबैक = परमाणु ()
  • RootAttributes = [गुण]

तत्व इनमें से कोई है:

  • {टैग, विशेषताएँ, सामग्री}
  • {टैग, सामग्री}
  • टैग
  • IOString
  • #xmlText {}
  • #xmlElement {}
  • #xmlPI {}
  • #xmlComment {}
  • #xmlDecl {}

सरल-स्वरूप संरचना {Tag, Attributes, Content} , {Tag, Content} या Tag जहां:

  • टैग = परमाणु ()
  • गुण = [{नाम, मान} | #xmlAttribute {}]
  • नाम = परमाणु ()
  • मान = IOString | परमाणु () | पूर्णांक ()

xmerl लिए संदर्भ पुस्तिका भी देखें

यदि आप 2003 से एक काले हार्ले डेविडसन 1200 सीसी स्पोर्टस्टर मोटरसाइकिल के बारे में जानकारी जोड़ना चाहते हैं जो कि मोटरसाइकिलों में नए आकार में है। xml दस्तावेज़ आप डेटा को सरल-रूप में डेटा संरचना में रख सकते हैं जैसे:

Data =
  {bike,
     [{year,"2003"},{color,"black"},{condition,"new"}],
     [{name,
         [{manufacturer,["Harley Davidsson"]},
          {brandName,["XL1200C"]},
          {additionalName,["Sportster"]}]},
      {engine,
         ["V-engine, 2-cylinders, 1200 cc"]},
      {kind,["custom"]},
      {drive,["belt"]}]}    

इस डेटा को motorcycles.xml दस्तावेज़ के अंत में संलग्न करने के लिए आपको फ़ाइल को पार्स करना होगा और डेटा को मूल तत्व सामग्री के अंत में जोड़ना होगा।

{RootEl,Misc}=xmerl_scan:file('motorcycles.xml'),
#xmlElement{content=Content} = RootEl,
NewContent=Content++lists:flatten([Data]),
NewRootEl=RootEl#xmlElement{content=NewContent},    

फिर आप इसे export_simple / 2 फ़ंक्शन के माध्यम से चला सकते हैं:

{ok,IOF}=file:open('new_motorcycles.xml',[write]),
Export=xmerl:export_simple([NewRootEl],xmerl_xml),
io:format(IOF,"~s~n",[lists:flatten(Export)]),    

परिणाम होगा:

<?xml version="1.0"?><motorcycles>
  <bike year="2000" color="black">
    <name>
      <manufacturer>Suzuki</manufacturer>
      <brandName>Suzuki VL 1500</brandName>
      <additionalName>Intruder</additionalName>
    </name>
    <engine>V-engine, 2-cylinders, 1500 cc</engine>
    <kind>custom</kind>
    <drive>cardan</drive>
    <accessories>Sissy bar, luggage carrier,V&amp;H exhaust pipes</accessories>
  </bike>
  <date>2004.08.25</date>
  <bike year="1983" color="read pearl">
    <name>
      <manufacturer>Yamaha</manufacturer>
      <brandName>XJ 400</brandName>
    </name>
    <engine>4 cylinder, 400 cc</engine>
    <kind>alround</kind>
    <drive>chain</drive>
    <comment>Good shape!</comment>
  </bike>
<bike year="2003" color="black" condition="new"><name><manufacturer>Harley Davidsson</manufacturer><brandName>XL1200C</brandName><additionalName>Sportster</additionalName></name><engine>V-engine, 2-cylinders, 1200 cc</engine><kind>custom</kind><drive>belt</drive></bike></motorcycles>

यदि मूल दस्तावेज में समान इंडेंटेशन और न्यूलाइन्स प्राप्त करना महत्वपूर्ण है, तो आपको उपयुक्त स्थानों में स्पेस और न्यूलाइन वैल्यू के साथ #xmlText {} रिकॉर्ड जोड़ना होगा। मूल प्रोलॉग को रखने के लिए भी आवश्यक हो सकता है जहां DTD संदर्भित है। यदि हां, तो export_simple/3 लिए export_simple/3 {prolog,Value} पास करना संभव है। निम्न उदाहरण कोड पिछले उदाहरण में उन परिवर्तनों को ठीक करता है:

    Data =
      [#xmlText{value="  "},
       {bike,[{year,"2003"},{color,"black"},{condition,"new"}],
             [#xmlText{value="\
    "},
              {name,[#xmlText{value="\
      "},
                     {manufacturer,["Harley Davidsson"]},
                     #xmlText{value="\
      "},
                     {brandName,["XL1200C"]},
                     #xmlText{value="\
      "},
                     {additionalName,["Sportster"]},
                     #xmlText{value="\
    "}]},
              {engine,["V-engine, 2-cylinders, 1200 cc"]},
              #xmlText{value="\
    "},
              {kind,["custom"]},
              #xmlText{value="\
    "},
              {drive,["belt"]},
              #xmlText{value="\
  "}]},
       #xmlText{value="\
"}],
    ...
    NewContent=Content++lists:flatten([Data]),
    NewRootEl=RootEl#xmlElement{content=NewContent},
    ...
    Prolog = ["<?xml version=\\"1.0\\" encoding=\\"utf-8\\" ?>
<!DOCTYPE motorcycles SYSTEM \\"motorcycles.dtd\\">\
"],
    Export=xmerl:export_simple([NewRootEl],xmerl_xml,[{prolog,Prolog}]),
    ...    

परिणाम होगा:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE motorcycles SYSTEM "motorcycles.dtd">
<motorcycles>
  <bike year="2000" color="black">
    <name>
      <manufacturer>Suzuki</manufacturer>
      <brandName>Suzuki VL 1500</brandName>
      <additionalName>Intruder</additionalName>
    </name>
    <engine>V-engine, 2-cylinders, 1500 cc</engine>
    <kind>custom</kind>
    <drive>cardan</drive>
    <accessories>Sissy bar, luggage carrier,V&amp;H exhaust pipes</accessories>
  </bike>
  <date>2004.08.25</date>
  <bike year="1983" color="read pearl">
    <name>
      <manufacturer>Yamaha</manufacturer>
      <brandName>XJ 400</brandName>
    </name>
    <engine>4 cylinder, 400 cc</engine>
    <kind>alround</kind>
    <drive>chain</drive>
    <comment>Good shape!</comment>
  </bike>
  <bike year="2003" color="black" condition="new">
    <name>
      <manufacturer>Harley Davidsson</manufacturer>
      <brandName>XL1200C</brandName>
      <additionalName>Sportster</additionalName>
    </name><engine>V-engine, 2-cylinders, 1200 cc</engine>
    <kind>custom</kind>
    <drive>belt</drive>
  </bike>
</motorcycles>

1.6 उदाहरण: XML को HTML में बदलना

मान लें कि आप motorcycles.xml दस्तावेज़ को HTML में बदलना चाहते हैं। यदि आप XML दस्तावेज़ के रूप में समान HTML डॉक्यूमेंट की संरचना और टैग चाहते हैं तो आप xmerl:export/2 फंक्शन का उपयोग कर सकते हैं। निम्नलिखित:

2> {Doc,Misc}=xmerl_scan:file('motorcycles.xml').
{{xmlElement,motorcycles,
             motorcycles,
             [],
             {xmlNamespace,[],[]},
             [],
             1,
             [],
             [{xmlText,[{motorcycles,1}],1,[],"\
  ",text},
              {xmlElement,bike,
...
3> DocHtml=xmerl:export([Doc],xmerl_html).
["<!DOCTYPE HTML PUBLIC \\"",
 "-//W3C//DTD HTML 4.01 Transitional//EN",
 "\\"",
 [],
 ">\
",
 [[["<","motorcycles",">"],
   ["\
  ",
    [["<",
      "bike",
      [[" ","year","=\\"","2000","\\""],[" ","color","=\\"","black","\\""]],
      ">"],
...    

result_export.html परिणाम result_export.html

शायद आप मानव पढ़ने के लिए कुछ और व्यवस्था करना चाहते हैं। मान लीजिए कि आप मोटरसाइकिल के प्रत्येक समूह के लिंक के साथ शुरुआत में सभी विभिन्न ब्रांडों को सूचीबद्ध करना चाहते हैं। आप सभी मोटरसाइकिलों को ब्रांड द्वारा क्रमबद्ध करना चाहते हैं, फिर इसके ऊपर कुछ आकर्षक रंग। इस प्रकार आप तत्वों के क्रम को पुनर्व्यवस्थित करते हैं और मनमाने ढंग से HTML टैग्स में डालते हैं। यह XSL Transformation (XSLT) से xmerl में कार्यक्षमता के माध्यम से संभव है।

भले ही निम्न उदाहरण XML से HTML में डेटा को बदलने का एक तरीका दिखाता है, यह अन्य स्वरूपों में परिवर्तनों पर भी लागू होता है।

xmerl_xs पूरे XSLT विनिर्देश लेकिन मूल कार्यक्षमता को लागू नहीं करता है। सभी विवरणों के लिए reference manual

सबसे पहले, xmerl_xs कार्यक्षमता के बारे में कुछ शब्द:

आपको किस प्रकार का आउटपुट चाहिए, यह नियंत्रित करने में सक्षम होने के लिए आपको टेम्पलेट फ़ंक्शन लिखना होगा। इस प्रकार यदि आप <p> टैग में bike तत्व को एनकोड करना चाहते हैं, तो आप केवल एक फ़ंक्शन लिखते हैं:

template(E = #xmlElement{name='bike'}) ->
    ["<p>",xslapply(fun template/1,E),"</p>"];    

xslapply साथ आप XSLT प्रोसेसर को बताते हैं कि किस क्रम में इसे XML संरचना को पार करना चाहिए। डिफ़ॉल्ट रूप से यह प्रीऑर्डर ट्रैवर्सल में चला जाता है, लेकिन निम्नलिखित के साथ हम उस ऑर्डर को तोड़ने के लिए एक जानबूझकर पसंद करते हैं:

template(E = #xmlElement{name='bike'}) ->
    ["<p>",xslapply(fun template/1,select("bike/name/manufacturer")),"</p>"];    

यदि आप XML तत्व या किसी विशेषता की सामग्री का उत्पादन करना चाहते हैं, तो आपको value_of फ़ंक्शन द्वारा स्ट्रिंग के रूप में मूल्य मिलेगा:

template(E = #xmlElement{name='motorcycles'}) ->
    ["<p>",value_of(select("bike/name/manufacturer",E),"</p>"];    

Xmerl_xs फ़ंक्शन में आप एक चयन (स्ट्रिंग) कॉल प्रदान कर सकते हैं, जो एक XPath कार्यक्षमता है। अधिक जानकारी के लिए xmerl_xs tutorial देखें।

अब, उस उदाहरण पर वापस जाएं जहां हम आउटपुट को अधिक व्यवस्थित बनाना चाहते थे। टेम्पलेट के साथ:

template(E = #xmlElement{name='motorcycles'}) ->
    [    "<head>\
<title>motorcycles</title>\
</head>\
",
         "<body>\
",
\011 "<h1>Used Motorcycles</h1>\
",
\011 "<ul>\
",
\011 remove_duplicates(value_of(select("bike/name/manufacturer",E))),
\011 "\
</ul>\
",
\011 sort_by_manufacturer(xslapply(fun template/1, E)),
         "</body>\
",
\011 "</html>\
"];    

हम शीर्ष तत्व पर मेल खाते हैं और एक HTML बॉडी में आंतरिक भागों को एम्बेड करते हैं। फिर हम सभी मोटरसाइकिल ब्रांडों के स्ट्रिंग मान निकालते हैं, उन्हें हटाते हैं और डुप्लिकेट को remove_duplicates(value_of(select("bike/name/manufacturer", E))) द्वारा remove_duplicates(value_of(select("bike/name/manufacturer", E))) । हम शीर्ष तत्व के उप-निर्माण की प्रक्रिया भी करते हैं और इसे एक फ़ंक्शन में पास करते हैं जो इस उदाहरण की शुरुआत में कार्य सूत्रीकरण के अनुसार ब्रांड द्वारा सभी मोटरसाइकिल जानकारी को सॉर्ट करता है।

अगला टेम्पलेट bike तत्व पर मेल खाता है:

template(E = #xmlElement{name='bike'}) ->
    {value_of(select("name/manufacturer",E)),["<dt>",xslapply(fun template/1,select("name",E)),"</dt>",
    "<dd><ul>\
",
    "<li style="color:green">Manufacturing year: ",xslapply(fun template/1,select("@year",E)),"</li>\
",
    "<li style="color:red">Color: ",xslapply(fun template/1,select("@color",E)),"</li>\
",
    "<li style="color:blue">Shape : ",xslapply(fun template/1,select("@condition",E)),"</li>\
",
    "</ul></dd>\
"]};    

यह मोटरसाइकिल के ब्रांड और आउटपुट प्रारूप के साथ एक तुक बनाता है। हम ब्रांड नाम का उपयोग केवल छँटाई उद्देश्य के लिए करते हैं। हमें "खंड में निर्मित" template(E) -> built_in_rules(fun template/1, E). साथ टेम्पलेट फ़ंक्शन को समाप्त करना होगा template(E) -> built_in_rules(fun template/1, E).

पूरा कार्यक्रम मोटरसाइकिल 2html.erl है:

%%%-------------------------------------------------------------------
%%% File    : motorcycles2html.erl
%%% Author  : Bertil Karlsson <[email protected]>
%%% Description : 
%%%
%%% Created :  2 Sep 2004 by Bertil Karlsson <[email protected]>
%%%-------------------------------------------------------------------
-module(motorcycles2html).

-include_lib("xmerl/include/xmerl.hrl").

-import(xmerl_xs, 
	[ xslapply/2, value_of/1, select/2, built_in_rules/2 ]).

-export([process_xml/1,process_to_file/2,process_to_file/1]).

process_xml(Doc) ->
    template(Doc).

process_to_file(FileName) ->
    process_to_file(FileName,'motorcycles.xml').

process_to_file(FileName,XMLDoc) ->
    case file:open(FileName,[write]) of
	{ok,IOF} ->
	    {XMLContent,_} = xmerl_scan:file(XMLDoc),
	    TransformedXML=process_xml(XMLContent),
	    io:format(IOF,"~s",[TransformedXML]),
	    file:close(IOF);
	{error,Reason} ->
	    io:format("could not open file due to ~p.~n",[Reason])
    end.

%%% templates
template(E = #xmlElement{name='motorcycles'}) ->
    [    "<head>\n<title>motorcycles</title>\n</head>\n",
         "<body>\n",
	 "<h1>Used Motorcycles</h1>\n",
	 "<ul>\n",
	 remove_duplicates(value_of(select("bike/name/manufacturer",E))),
	 "\n</ul>\n",
	 sort_by_manufacturer(xslapply(fun template/1, E)),
         "</body>\n",
	 "</html>\n"];
template(E = #xmlElement{name='bike'}) ->
    {value_of(select("name/manufacturer",E)),["<dt>",xslapply(fun template/1,select("name",E)),"</dt>",
    "<dd><ul>\n",
    "<li style=\"color:green\">Manufacturing year: ",xslapply(fun template/1,select("@year",E)),"</li>\n",
    "<li style=\"color:red\">Color: ",xslapply(fun template/1,select("@color",E)),"</li>\n",
    "<li style=\"color:blue\">Shape : ",xslapply(fun template/1,select("@condition",E)),"</li>\n",
    "</ul></dd>\n"]};
template(E) -> built_in_rules(fun template/1, E).


%%%%%%%%%%% helper routines  

%% sorts on the bike name element, unwraps the bike information and
%% inserts a line feed and indentation on each bike element.
sort_by_manufacturer(L) ->
    Tuples=[X1||X1={_,_} <- L],
    SortedTS = lists:keysort(1,Tuples),
    InsertRefName_UnWrap=
	fun([{[Name],V}|Rest],Name,F)->
		[V|F(Rest,Name,F)];
	   ([{[Name],V}|Rest],_PreviousName,F) ->
		[["<a name=\"",Name,"\"></>"],V|F(Rest,Name,F)];
	   ([],_,_) -> []
	end,
    SortedRefed=InsertRefName_UnWrap(SortedTS,no_name,InsertRefName_UnWrap),
%    SortedTs=[Y||{X,Y}<-lists:keysort(1,Tuples)],
    WS = "\n    ",
    Fun=fun([H|T],Acc,F)->
		F(T,[H,WS|Acc],F);
	   ([],Acc,_F)->
		lists:reverse([WS|Acc])
	end,
    if length(SortedRefed) > 0 ->
	    Fun(SortedRefed,[],Fun);
       true -> []
    end.

    
%% removes all but the first of an element in L and inserts a html
%% reference for each list element.
remove_duplicates(L) ->
    remove_duplicates(L,[]).

remove_duplicates([],Acc) -> 
    make_ref(lists:sort(lists:reverse(Acc)));
remove_duplicates([A|L],Acc) -> 
    case lists:delete(A,L) of
	L ->
	    remove_duplicates(L,[A|Acc]);
	L1 -> 
	    remove_duplicates([A|L1],[Acc])
    end.

make_ref([]) -> [];
make_ref([H]) when is_atom(H) ->
    "<ul><a href=\"#"++atom_to_list(H)++"\">"++atom_to_list(H)++"</a></ul>";
make_ref([H]) when is_list(H) ->
    "<ul><a href=\"#"++H++"\">\s"++H++"</a></ul>";
make_ref([H|T]) when is_atom(H) ->
    ["<ul><a href=\"#"++atom_to_list(H)++"\">\s"++atom_to_list(H)++",\n</a></ul>"
     |make_ref(T)];
make_ref([H|T]) when is_list(H) ->
    ["<ul><a href=\"#"++H++"\">\s"++H++",\n</a></ul>"|make_ref(T)].

अगर हम इसे इस तरह चलाते हैं: motorcycles2html:process_to_file('result_xs.html', 'motorcycles2.xml'). परिणाम result_xs.html होगा। जब इनपुट फ़ाइल पिछले "मोटरसाइकिल" XML फ़ाइलों के समान संरचना की होती है, लेकिन इसमें थोड़ी अधिक 'बाइक' तत्व होते हैं और 'निर्माता' तत्व क्रम में नहीं होते हैं।