2010-12-28 14 views
5

मेरे पास 2 एक्सएमएल फाइलें हैं। Xslt का उपयोग करके मैं दोनों फ़ाइलों की तुलना कैसे बराबर या नहीं कर सकता? यदि बराबर नहीं है तो दूसरे xml में परिवर्तन कब होते हैं?xslt के साथ दो एक्सएमएल फाइलों की तुलना करें?

उत्तर

0

एक्सएसएलटी एक एक्सएमएल बोली को दूसरे में बदलने के लिए सबसे अच्छा उपयोग किया जाता है।

एक्सएमएल फाइलों की तुलना करने के लिए, मैं आपके प्लेटफॉर्म पर एक्सएमएल पार्सर का उपयोग करूंगा और इसका उपयोग कर दस्तावेजों की तुलना करूंगा।

यह संभव है दोनों की तुलना करने के लिए, लेकिन यदि आपके पास अन्य विकल्प हैं, तो मैं इसके खिलाफ सलाह दूंगा।

4

XPath 2.0 में आप fn:deep-equal का उपयोग कर सकते हैं।

XSLT 1.0 है, यह स्टाइलशीट में एक ही पैटर्न के बाद:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:param name="pSource2" select="'emp2.xml'"/> 
    <xsl:template match="/*"> 
     <xsl:variable name="vDeep-equal"> 
      <xsl:apply-templates select="." mode="deep-equal"> 
       <xsl:with-param name="pTarget" select="document($pSource2)/*"/> 
      </xsl:apply-templates> 
     </xsl:variable> 
     <xsl:choose> 
      <xsl:when test="normalize-space($vDeep-equal)"> 
       <xsl:text>Documents are different</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>Documents are deep equal</xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
    <xsl:template match="*" mode="deep-equal"> 
     <xsl:param name="pTarget"/> 
     <xsl:choose> 
      <xsl:when test="$pTarget/self::* and 
          local-name()=local-name($pTarget) and 
          namespace-uri()=namespace-uri($pTarget) and 
          count(@*)=count($pTarget/@*) and 
          count(*|text()[normalize-space()]) = 
           count($pTarget/*| 
            $pTarget/text()[normalize-space()])"> 
       <xsl:for-each select="@*"> 
        <xsl:if test="$pTarget/@*[name()=name(current())] != ."> 
         <xsl:text>false</xsl:text> 
        </xsl:if> 
       </xsl:for-each> 
       <xsl:for-each select="*|text()[normalize-space()]"> 
        <xsl:variable name="vPosition" select="position()"/> 
        <xsl:apply-templates select="." mode="deep-equal"> 
         <xsl:with-param name="pTarget" 
             select="($pTarget/*| 
               $pTarget/text() 
                [normalize-space()]) 
                  [$vPosition]"/> 
        </xsl:apply-templates> 
       </xsl:for-each> 
      </xsl:when> 
      <xsl:otherwise>false</xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
    <xsl:template match="text()" mode="deep-equal"> 
     <xsl:param name="pTarget"/> 
     <xsl:if test="not($pTarget/self::text() and 
         string() = string($pTarget))"> 
      <xsl:text>false</xsl:text> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

आउटपुट:

Documents are different 
+0

@Alejandro: अच्छा प्रयास है, लेकिन आप एक नाम स्थान, खाली स्थान के-केवल नोड्स, नाम स्थान नोड्स, पीआई नोड्स और टिप्पणी नोड्स में संबंधित नोड्स पर विचार नहीं किया है। जैसा कि हम जानते हैं, दो नोड्स के अलग-अलग नाम हो सकते हैं और फिर भी समकक्ष हो सकते हैं - जैसे: 'एच: एचटीएमएल' और' एचटीएमएल'। जो लोग "समानता" के लिए दो एक्सएमएल दस्तावेज़ों की तुलना करने के लिए कह रहे हैं, वे आमतौर पर नहीं जानते कि वे वास्तव में क्या पूछ रहे हैं। –

+0

@ डिमिट्री: आप नामों के बारे में सही हैं। मैंने गलत तरीके से XPath 2.0 'नोड-नाम()' का अनुवाद किया है। मैं इसे सही कर दूंगा। अन्य नोड प्रकार के बारे में: क्योंकि "समानता" को अधिक सटीक रूप से परिभाषित किया जाना चाहिए, मैंने 'गहरी-बराबर' परिभाषा ली है जो टिप्पणियों या पीआई बच्चों पर विचार नहीं करता है, स्कोप नामस्थानों में और न ही सफेद स्थान केवल ** तत्वों ** के लिए टेक्स्ट नोड्स। –

0

यह स्टाइलशीट मैं नोड्स में अलग आदेश के साथ दो एक्सएमएल फाइल तुलना करने के लिए लिखा था और विशेषताओं का है। यह दो टेक्स्ट फाइलें उत्पन्न करेगा, जिसमें सभी पत्ते नोड्स पथ की ऑर्डर की गई सूची होगी। मतभेदों को जानने या एक्सएसएलटी को बढ़ाने के लिए किसी भी पाठ तुलना टूल का उपयोग करें जो आप चाहते हैं।

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="text" indent="no" omit-xml-declaration="yes" name="output" /> 

<xsl:param name="OTHERFILENAME">xml_file_to_diff.xml</xsl:param> 
<xsl:param name="ORIGINAL_OUTPUT_FILENAME">ORIGINAL.txt</xsl:param> 
<xsl:param name="OTHER_OUTPUT_FILENAME">OTHER.txt</xsl:param> 

<xsl:template match="/"> 
    <xsl:call-template name="convertXMLHierarchyToFullPath"> 
     <xsl:with-param name="node" select="*"/> 
     <xsl:with-param name="filename" select="$ORIGINAL_OUTPUT_FILENAME"/> 
    </xsl:call-template> 
    <xsl:call-template name="convertXMLHierarchyToFullPath"> 
     <xsl:with-param name="node" select="document($OTHERFILENAME)/*"/> 
     <xsl:with-param name="filename" select="$OTHER_OUTPUT_FILENAME"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="convertXMLHierarchyToFullPath"> 
    <xsl:param name="node"/> 
    <xsl:param name="filename"/> 

    <xsl:variable name="unorderedFullPath"> 
     <xsl:apply-templates select="$node"/> 
    </xsl:variable> 

    <xsl:result-document href="{$filename}" format="output"> 
     <xsl:for-each select="$unorderedFullPath/*"> 
      <xsl:sort select="@path" data-type="text"/> 
      <xsl:value-of select="@path"/> 
      <xsl:text>&#xA;</xsl:text> 
     </xsl:for-each> 
    </xsl:result-document> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:if test="not(*)"> 
     <leaf> 
      <xsl:attribute name="path"> 
       <xsl:for-each select="ancestor-or-self::*"> 
        <xsl:value-of select="name()"/> 
        <xsl:for-each select="@*"> 
         <xsl:sort select="name()" data-type="text"/> 
         <xsl:text>[</xsl:text> 
         <xsl:value-of select="name()"/> 
         <xsl:text>:</xsl:text> 
         <xsl:value-of select="."/> 
         <xsl:text>]</xsl:text> 
        </xsl:for-each> 
        <xsl:text>/</xsl:text> 
       </xsl:for-each> 
       <xsl:value-of select="."/> 
      </xsl:attribute> 
     </leaf> 
    </xsl:if> 
    <xsl:apply-templates select="*"/> 
</xsl:template> 

</xsl:stylesheet> 
संबंधित मुद्दे