我想計算使用XSL/XSLT的兩個XML文件或節點之間的差異。是否有任何樣式表可用或者簡單的方法?XML Diff:如何使用XSLT生成XML差異?
回答
有趣的問題!我曾經嘗試過做類似的事情,涉及到兩個XML源,而我的經驗是,沒有辦法。
您可以使用XSL的工具來包含用戶構建的函數,並編寫一些非常流暢的代碼。但我真的看不到它。
如果我要做這樣的事情,我會使用DOM4J並行處理這兩個XML文件,這使我可以通過編程方式輕鬆遍歷代碼並執行詳細的子查詢。
試圖在XSLT中做到這一點將證明你是一個天才或驅使你陷入瘋狂。
XSLT是數據驅動的,也就是說,它通過單個源XML文件自上而下地查找XSL樣式表中的模板匹配。模板並不知道它們在數據中的位置,只是在匹配時才運行它們的代碼。您可以引用另一個XML源,但該程序將根據原始源的遍歷運行。
因此,例如,當您到達第<blarg>
的第n個子元素時,可以使用document()
函數在第二個XML中查找<blarg>
的第n個子元素。但是這種有用性取決於你的XML的結構以及你想要做的比較。
這種行爲與大多數傳統腳本相反,它們通過程序代碼自上而下運行,在指示時調用數據文件。後者 - 拉處理 - 是您可能需要比較兩個XML源的東西。一旦出現差異,XSLT將進行比較分析。
有辦法做到這一點,但我不會說這很簡單。
在我使用所謂diffmk一個開源工具過去,這將產生一個輸出XML有額外的標籤,以顯示什麼已添加/刪除...
我不得不寫一個額外的樣式表,然後將其轉換這個轉換成更可讀的HTML報告。
XMLSpy Diff Dog等一些diff工具不錯,但成本很高。
這不是一個謎!以下是一般步驟:
@carillonator對XSLT如何處理文檔是正確的。因此,爲了使它更容易,我們將文檔的兩個版本合併到一個文檔中,您可以使用它來運行XSLT diff(您可以通過命令行使用bash,或者使用您正在使用的任何編程語言,甚至另一種語言XSLT轉換[管道])。這只是一個封裝:
<diff_container> <version1> ... first version here </version1> <version2> ... second version here </version2> </diff_container>
然後我們通過我們的XSLT DIFF運行此文件中,然後XSLT有簡單遍歷樹,並比較兩個版本之間的節點的工作。這可以從非常簡單(是一個元素改變?移動?刪除?)到半複雜。對XPath的很好理解使得這非常簡單。
就像之前說的一樣,你在不同的環境中工作,所以與Diff Dog這樣的工具相比,你受到的限制。然而,在XSLT中使用算法的好處也可能具有實際價值。
希望這對我有所幫助。乾杯!
如果你的意思是差異什麼是一樣的東西檢查一個文件(或節點)是否存在的項目而不是另一個,你可以使用XPath鍵()函數有第三個參數
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs ="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xsl xs">
<xsl:param name="doc2diff" required="yes"/>
<!-- docB is root node of the "second" document -->
<xsl:variable name="docB" select="document($doc2diff)"/>
<!-- docA is the root node of the first document -->
<xsl:variable name="docA" select="/"/>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:key name="items" match="Item" use="someId"/>
<xsl:template match="/">
<ListOfItems>
<In_A_NotIn_B>
<xsl:apply-templates select="Item">
<xsl:with-param name="otherDocument" select="$docB"/>
</xsl:apply-templates>
</In_A_NotIn_B>
<In_B_NotIn_A>
<xsl:apply-templates select="Item">
<xsl:with-param name="otherDocument" select="$docA"/>
</xsl:apply-templates>
</In_B_NotIn_A>
</ListOfItems>
</xsl:template>
<xsl:template match="Item">
<xsl:param name="otherDocument"/>
<xsl:variable name="SOMEID" select="someId"/>
<xsl:if test="empty(key('items', $SOMEID, $otherDocument))">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>`
這是我寫的樣式表是爲了比較在節點和屬性中具有不同順序的兩個XML文件,它將生成兩個包含有序列表的所有葉節點路徑的文本文件。使用任何文本比較工具來發現差異或增強XSLT以做你想做的事。
<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>
</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>
發現這個職位最近,但無論如何,我會分享我對這類問題的解決方案。我有和@Vincent一樣的需求:比較2個不同的XML文件,並快速查看它們之間的差異。快速差異有太多的行匹配,因爲文件沒有排序,所以我決定使用XSLT對文件進行排序,然後使用WinMerge手動比較這兩個xml文件(一個簡單的unix diff也可以完成這項工作)。
這裏是那種我的XML文件中的XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:sort select="name()" />
<xsl:sort select="@*" />
<xsl:sort select="*" />
<xsl:sort select="text()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
- 1. 如何使用Perl和XSLT生成XML?
- 2. 使用XSLT自動生成XML模式
- 3. 使用CGI生成XML和XSLT
- 4. 使用XSLT生成SOAP XML的問題
- 5. XSLT使用兄弟節點生成XML
- 6. 使用XML和XSLT生成SQL
- 7. 使用xml和xslt生成動態圖
- 8. 如何從XML樣本生成XSLT
- 9. 如何從xml生成xslt文件
- 10. XSLT - 生成HTML從XML
- 11. XSLT處理生成的XML
- 12. XML和XSLT生成CSS?
- 13. 拆分成XML使用XSLT
- 14. 如何使用XSLT從XML
- 15. XSLT XML轉換成XML通過XSLT
- 16. 如何用Perl的XML :: Simple生成XML?
- 17. XML使用XSLT
- 18. XML 2使用XSLT的XML
- 19. 如何生成XML?
- 20. 如何生成XML
- 21. 使用XSLT計算差異
- 22. 用PHP解析差異(用git-diff生成)
- 23. XSLT解析XML以生成Word文檔
- 24. 強制xslt生成「xml」域名
- 25. 如何使用libxml2生成XML文件?
- 26. 如何使用XMLSerializer生成XML?
- 27. 如何使用雙表生成XML?
- 28. 如何使用lxml.objectify生成XML
- 29. 如何使用php生成xml文件
- 30. 如何使用Rails生成XML?
+1只是爲了它的野心,BTW這XSLT的版本是你找這工作 – AnthonyWJones 2009-11-20 15:50:53
的目標將是差異兩個節點在同一個XML文件中,那更可行嗎? – Vincent 2009-11-23 15:32:59
您必須用XML術語定義相同和不同的含義。作爲參考看看這個問題http://stackoverflow.com/questions/4546190/compare-two-xml-files-with-xslt – 2011-02-03 00:00:46