XSLT

2012-10-08 22 views
5

के साथ एक साधारण एक्सएमएल के लिए मुएनचियन ग्रुपिंग को लागू करना Muenchian grouping विवरण में कैसे काम करता है?XSLT

<CLIENTS> 
    <CLIENT> 
     <NAME>John</NAME> 
     <ACCOUNT_NUMBER>1424763562761</ACCOUNT_NUMBER> 
     <LAST_USED>2012-10-03</LAST_USED> 
     <AMOUNT>5000</AMOUNT> 

    </CLIENT> 
    <CLIENT> 
     <NAME>John</NAME> 
     <ACCOUNT_NUMBER>543667543732</ACCOUNT_NUMBER> 
     <LAST_USED>2012-10-02</LAST_USED> 
     <AMOUNT>10000</AMOUNT> 
    </CLIENT> 
     ... 

मैं नाम नोड द्वारा समूह करना चाहते हैं:

मैं एक साधारण XML दस्तावेज़ एक डेटाबेस से उत्पन्न की है। मैं वांछित ouput निम्नलिखित कैसे हो सकता है?

<ClIENTS> 
    <CLIENT> 
     <NAME>John</NAME> 
     <ACCOUNT> 
      <ACCOUNT_NUMBER>1424763562761</ACCOUNT_NUMBER> 
      <LAST_USED>2012-10-03</LAST_USED> 
      <AMOUNT>5000</AMOUNT> 
     </ACCOUNT> 
     <ACCOUNT> 
      <ACCOUNT_NUMBER>543667543732</ACCOUNT_NUMBER> 
      <LAST_USED>2012-10-03</LAST_USED> 
      <AMOUNT>10000</AMOUNT> 
     </ACCOUNT> 
     .... 
</CLIENTS> 

उत्तर

8

पढ़ें www.jenitennison.com/xslt/grouping/muenchian.xml, के लिए कोड के साथ एक सहायता परिभाषित एक महत्वपूर्ण

<xsl:key name="client-by-name" match="CLIENT" use="NAME"/> 

तो के रूप में

<xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 


<xsl:template match="CLIENTS"> 
    <xsl:copy> 
    <xsl:apply-templates select="CLIENT[generate-id() = generate-id(key('client-by-name', NAME)[1])]" mode="group"/> 
    <xsl:copy> 
</xsl:template> 

<xsl:template match="CLIENT" mode="group"> 
    <xsl:copy> 
    <xsl:copy-of select="NAME"/> 
    <xsl:apply-templates select="key('client-by-name', NAME)"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="CLIENT"> 
    <ACCOUNT> 
    <xsl:apply-templates select="node()[not(self::NAME)]"/> 
    </ACCOUNT> 
</xsl:template> 

[संपादित करें] टेम्पलेट का उपयोग आप तो की XSLT 2.0 उपयोग करना चाहते हैं बेशक आपको मुएनचियन समूह की आवश्यकता नहीं है, इसके बजाय आप

<xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* , node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="CLIENTS"> 
    <xsl:copy> 
    <xsl:for-each-group select="CLIENT" group-by="NAME"> 
     <CLIENT> 
     <xsl:apply-templates select="NAME, current-group()"/> 
     </CLIENT> 
    </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="CLIENT"> 
    <ACCOUNT> 
    <xsl:apply-templates select="node() except NAME"/> 
    </ACCOUNT> 
</xsl:template> 
का उपयोग करें
+0

उपयोगी उत्तर लोगों के लिए बहुत धन्यवाद। Xslt 2.0 xls: प्रत्येक-समूह के लिए एक ही समस्या को हल करना संभव है? यदि हां, तो क्या आप समाधान पोस्ट कर सकते हैं? – user1728778

+0

@ user1728778 - हाँ, यह संभव है। कॉम्पैक्ट एक्सएसएलटी 2.0 समाधान के लिए कृपया मेरा उत्तर देखें। – ABach

4

जेनी टेनिसन यहाँ Muenchian समूह प्रदर्शन करने के लिए आवश्यक कदम टूट जाता है:

http://www.jenitennison.com/xslt/grouping/muenchian.html

अनिवार्य रूप से, XSLT का उपयोग नोड के लिए एक कुंजी सौंपने के लिए, इस कुंजी अगर वहाँ दस्तावेज़ में समान नोड्स है दोहराया जा सकता है। एक्सएसएलटी तब प्रत्येक कुंजी के माध्यम से जाता है, और आपको मिलान कुंजी के साथ नोड्स आउटपुट करने की अनुमति देता है।

तो, मार्टिन जवाब में, इस लाइन का नाम नोड की सामग्री पर आधारित प्रत्येक ग्राहक के लिए एक महत्वपूर्ण पैदा कर रही है (याद करता है, तो नाम कई ग्राहकों के लिए एक ही है, इसलिए होगा कुंजी):

<xsl:key name="client-by-name" match="CLIENT" use="NAME"/> 

फिर आप सभी चाबियाँ के माध्यम से जाने के लिए और प्रत्येक के (फिर मार्टिन जवाब का प्रयोग करके) पहले उदाहरण खोजने के लिए

<xsl:apply-templates select="CLIENT[generate-id() = generate-id(key('client-by-name', NAME)[1])]" mode="group"/> 

फिर आप उत्पादन करने में सक्षम होना ग्राहकों है कि कुंजी के मिलान के सभी लगाना चाहते हैं चाहते हैं कि उनके विवरण (फिर से, मार्टिन्स)

<xsl:apply-templates select="key('client-by-name', NAME)"/> 

यहाँ से आप ग्राहक विवरण

3

Muenchian ग्रुपिंग (@ मार्टिन जवाब के अनुसार) उत्पादन के लिए अन्य टेम्प्लेट आवश्यकता होगी अतिरेक जबकि समूहीकरण है कि एक और अधिक परंपरागत समूह रणनीति दूर करता है।

Muenchian समूहीकरण के बिना, टेम्पलेट्स आमतौर पर preceding-sibling या following-sibling, इस्तेमाल किया प्रत्येक समूह के पहले उम्मीदवार उदाहरण निर्धारित करने के लिए, और फिर समूह मिलान सभी नोड्स देखने के लिए एक दूसरे क्वेरी की आवश्यकता होगी इस प्रकार है:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 

    <xsl:template match="CLIENTS"> 
     <CLIENTS> 
      <!--Only find the 'first' instance of each client--> 
      <xsl:apply-templates select="CLIENT[not(NAME = preceding-sibling::CLIENT/NAME)]" mode="client"/> 
     </CLIENTS> 
    </xsl:template> 

    <xsl:template match="CLIENT" mode="client"> 
     <xsl:variable name="name" select="NAME"/> 
     <CLIENT> 
      <NAME> 
       <xsl:value-of select="$name"/> 
      </NAME> 
      <ACCOUNTS> 
       <!--Note that we now have to find the other matching clients *again* - this is the inefficiency that Muenchian grouping eliminates--> 
       <xsl:apply-templates select="/CLIENTS/CLIENT[NAME/text()=$name]" mode="account" /> 
      </ACCOUNTS> 
     </CLIENT> 
    </xsl:template> 

    <xsl:template match="CLIENT" mode="account"> 
     <ACCOUNT> 
      <!--Copy everything else except Name, which is the grouping key --> 
      <xsl:copy-of select="@* | *[not(local-name='NAME')]"/> 
     </ACCOUNT> 
    </xsl:template> 

</xsl:stylesheet> 
+2

+1 यह समझाने के लिए कि मुएनचियन ग्रुपिंग भी जरूरी क्यों है। – ABach

1

में पिछली टिप्पणी (मार्टिन के उत्तर के तहत), ओपी ने पूछा कि क्या इस समस्या को हल करने के लिए एक्सएसएलटी 2.0 के for-each-group तत्व का उपयोग किया जा सकता है।

जब यह एक्सएसएलटी 2।0 समाधान:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 
    <xsl:output omit-xml-declaration="no" indent="yes" /> 
    <xsl:strip-space elements="*" /> 

    <xsl:template match="/*"> 
    <CLIENTS> 
     <xsl:for-each-group select="CLIENT" group-by="NAME"> 
     <CLIENT> 
      <xsl:sequence select="NAME" /> 
      <xsl:for-each select="current-group()"> 
      <ACCOUNT> 
       <xsl:sequence select="*[not(self::NAME)]" /> 
      </ACCOUNT> 
      </xsl:for-each> 
     </CLIENT> 
     </xsl:for-each-group> 
    </CLIENTS> 
    </xsl:template> 

</xsl:stylesheet> 

... ओ पी के मूल एक्सएमएल के लिए लागू किया जाता है:

<CLIENTS> 
    <CLIENT> 
    <NAME>John</NAME> 
    <ACCOUNT_NUMBER>1424763562761</ACCOUNT_NUMBER> 
    <LAST_USED>2012-10-03</LAST_USED> 
    <AMOUNT>5000</AMOUNT> 
    </CLIENT> 
    <CLIENT> 
    <NAME>John</NAME> 
    <ACCOUNT_NUMBER>543667543732</ACCOUNT_NUMBER> 
    <LAST_USED>2012-10-02</LAST_USED> 
    <AMOUNT>10000</AMOUNT> 
    </CLIENT> 
</CLIENTS> 

... वांछित परिणाम का उत्पादन किया है:

<?xml version="1.0" encoding="utf-8"?> 
<CLIENTS> 
    <CLIENT> 
    <NAME>John</NAME> 
    <ACCOUNT> 
     <ACCOUNT_NUMBER>1424763562761</ACCOUNT_NUMBER> 
     <LAST_USED>2012-10-03</LAST_USED> 
     <AMOUNT>5000</AMOUNT> 
    </ACCOUNT> 
    <ACCOUNT> 
     <ACCOUNT_NUMBER>543667543732</ACCOUNT_NUMBER> 
     <LAST_USED>2012-10-02</LAST_USED> 
     <AMOUNT>10000</AMOUNT> 
    </ACCOUNT> 
    </CLIENT> 
</CLIENTS> 

स्पष्टीकरण:

जैसा कि आपने पहले से ही सही ढंग से अनुमान लगाया है, एक्सएसएलटी 2.0 ने for-each-group तत्व (और इसके संबंधित भागीदारों, जैसे current-group()) को अद्भुत/प्रभावशाली, अभी तक संभावित रूप से भ्रमित समूह पद्धतियों जैसे मुएनचियन विधि से दूर करने के लिए पेश किया है।