2010-06-10 11 views
5

में अद्वितीय रिकॉर्ड चुनना मुझे <xsl:for-each> लूप के संदर्भ में, XML दस्तावेज़ से केवल अद्वितीय रिकॉर्ड चुनना है। मैं एक्सएसएल 1.0 का उपयोग करने के लिए विजुअल स्टूडियो द्वारा सीमित हूं।एक्सएसएलटी/XPath

<availList> 
     <item> 
      <schDate>2010-06-24</schDate>    
      <schFrmTime>10:00:00</schFrmTime> 
      <schToTime>13:00:00</schToTime> 
      <variousOtherElements></variousOtherElements> 
     </item> 
     <item> 
      <schDate>2010-06-24</schDate>    
      <schFrmTime>10:00:00</schFrmTime> 
      <schToTime>13:00:00</schToTime> 
      <variousOtherElements></variousOtherElements> 
     </item> 
     <item> 
      <schDate>2010-06-25</schDate>    
      <schFrmTime>10:00:00</schFrmTime> 
      <schToTime>12:00:00</schToTime> 
      <variousOtherElements></variousOtherElements> 
     </item> 
     <item> 
      <schDate>2010-06-26</schDate>    
      <schFrmTime>13:00:00</schFrmTime> 
      <schToTime>14:00:00</schToTime> 
      <variousOtherElements></variousOtherElements> 
     </item> 
     <item> 
      <schDate>2010-06-26</schDate>    
      <schFrmTime>10:00:00</schFrmTime> 
      <schToTime>12:00:00</schToTime> 
      <variousOtherElements></variousOtherElements> 
     </item> 
    </availList> 

विशिष्टता तीन बच्चे तत्वों के मूल्य के आधार पर किया जाना चाहिए: schDate, schFrmTime और schToTime। यदि दो item तत्वों के पास सभी तीन बाल तत्वों के लिए समान मान हैं, तो वे डुप्लिकेट हैं। उपर्युक्त एक्सएमएल में, आइटम एक और दो डुप्लिकेट हैं। बाकी अद्वितीय हैं। जैसा ऊपर बताया गया है, प्रत्येक आइटम में अन्य तत्व होते हैं जिन्हें हम तुलना में शामिल नहीं करना चाहते हैं। 'विशिष्टता' उन तीन तत्वों, और अकेले उन लोगों का एक कारक होना चाहिए।

मैं निम्नलिखित के माध्यम से यह पूरा करने का प्रयास किया है:

availList/item[not(schDate = preceding:: schDate and schFrmTime = preceding:: schFrmTime and schToTime = preceding:: schToTime)] 

इसके पीछे विचार रिकॉर्ड चयन करने के लिए जहां एक ही schDate, schFrmTime और schToTime के साथ कोई पिछले तत्व नहीं है। हालांकि, इसका आउटपुट अंतिम आइटम गुम है। ऐसा इसलिए है क्योंकि मेरा XPath वास्तव में उन वस्तुओं को छोड़कर है जहां सभी बाल तत्व मान पूरे पिछले दस्तावेज़ के साथ मेल खाते हैं। कोई भी item अंतिम आइटम के सभी तत्वों से मेल खाता है - लेकिन क्योंकि प्रत्येक तत्व का मान व्यक्तिगत रूप से किसी अन्य आइटम में मौजूद होता है, अंतिम आइटम को बाहर रखा जाता है।

मैं प्रत्येक पूर्ववर्ती आइटम के लिएके लिए एक ही श्रेणीबद्ध मूल्यों एक concatenated स्ट्रिंग के रूप में सभी बच्चे मूल्यों की तुलना द्वारा सही परिणाम मिल सकता है। क्या कोई इस तरह से जानता है कि मैं ऐसा कर सकता हूं?

+0

अच्छा प्रश्न (+1)। XPath और XSLT समाधान के लिए मेरा उत्तर देखें। –

+1

कुंजी() का उपयोग करने वाली विधि को आमतौर पर मुएनचियन विधि के रूप में जाना जाता है: http://www.jenitennison.com/xslt/grouping/muenchian.html –

उत्तर

4

मैं एक भी XPath अभिव्यक्ति के रूप में:

/*/item[normalize-space() and not(. = preceding-sibling::item)] 

द्वितीय।अधिक कुशल (XSLT) कार्यान्वयन, कुंजियों का उपयोग:

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

<xsl:key name="kItemByVal" match="item" use="."/> 

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "*/item[generate-id() = generate-id(key('kItemByVal', .))] 
    "/> 
</xsl:template> 
</xsl:stylesheet> 

दोनों मैं और द्वितीय, जब प्रदान की XML दस्तावेज़ पर लागू सही ढंग से चयन/कॉपी निम्नलिखित नोड्स:

<item><schDate>2010-06-24</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>13:00:00</schToTime></item> 
<item><schDate>2010-06-25</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item> 
<item><schDate>2010-06-26</schDate><schFrmTime>13:00:00</schFrmTime><schToTime>14:00:00</schToTime></item> 
<item><schDate>2010-06-26</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item> 

अद्यतन : <item> में अन्य बच्चे हैं, तो यह परिवर्तन:

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

    <xsl:key name="kItemBy3Children" match="item" 
    use="concat(schDate, '+', schFrmTime, '+', schToTime)"/> 

<xsl:template match="/"> 
     <xsl:copy-of select= 
     "*/item[generate-id() 
       = generate-id(key('kItemBy3Children', 
           concat(schDate, 
             '+', schFrmTime, 
             '+', schToTime) 
           ) 
          ) 
       ] 
     "/> 
</xsl:template> 
</xsl:stylesheet> 

वांछित परिणाम उत्पन्न करता है।

+0

डिमिट्रे, आपके उत्तर के लिए बहुत बहुत धन्यवाद। मुझे डर है कि यह मेरे मामले के लिए काम नहीं करेगा, हालांकि - मैं क्षमा चाहता हूं कि मेरा प्रश्न लिखते समय मैं बहुत स्पष्ट नहीं था (मैंने बाद में इसे संपादित किया है)। समस्या यह है कि, हकीकत में, मेरे 'आइटम' तत्वों में कई अन्य उप-तत्व भी होते हैं जिन्हें इस बात की गिनती नहीं करनी चाहिए कि आइटम चुने गए हैं या नहीं। मैं वास्तव में 'असली' विशिष्टता की तलाश नहीं कर रहा हूं, मैं विशिष्ट बाल तत्व मानों में विशिष्टता की तलाश में हूं। मुझे यकीन है कि आपका जवाब दूसरों के लिए मूल्यवान होगा, हालांकि। दान –

+1

@ डैनियल-आई-एस: मैंने संशोधित समस्या के समाधान के साथ अपना उत्तर अपडेट किया है। –

+2

यह एक अच्छा जवाब है; आपका बहुत बहुत धन्यवाद। –

2

मैंने जो तकनीक देखी है वह दो पास में ऐसा करना है: आइटम को सभी तीन प्रमुख फ़ील्ड द्वारा क्रमबद्ध करें, और फिर प्रत्येक आइटम की तुलना अपने पिछले आइटम (सभी पिछली वस्तुओं के बजाय) से करें।

क्या आपके लिए दो अलग-अलग परिवर्तनों को चलाने के लिए व्यावहारिक है? यह समस्या को और आसान बनाता है।

मैंने तकनीक को Michael Kay's XSLT book के पुराने संस्करण में देखा। आप इसे अपने कुछ नमूना कोड में पा सकते हैं।

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

  • कोई संबंधित समस्या नहीं^_^