2013-05-25 34 views
1

我想比較以下兩個XML部分並生成第三個XML部分。XSL比較和合並兩個XML部分

1)

<Drive> 
    <Folders> 
    <Folder> 
     <name>folder1</name> 
     <Files> 
     <File> 
      <State>Writable</State> 
      <name>file1</name> 
     </File> 
     </Files> 
    </Folder> 
    </Folders> 
    <Files> 
    <File> 
     <State>Readable</State> 
     <name>file2</name> 
    </File> 
    </Files> 
</Drive> 

2)

<Partition> 
    <Directories> 
    <Directory> 
     <name>folder1</name> 
     <Unix-File> 
     <name>file1</name> 
     </Unix-File> 
    </Directory> 
    <Directory> 
     <name>folder-5</name> 
     <Unix-File> 
     <name>file-5</name> 
     </Unix-File> 
    </Directory> 
    </Directories> 
    <Unix-Files> 
    <Unix-File> 
     <name>file2</name> 
    </Unix-File> 
    </UnixFiles> 
</Partition> 

現在,

1)將所得的XML節應該包含所有具有相同的名稱作爲與Unix-fileDirectory元件在第一個XML節中有StateWritable

2)任何沒有任何匹配文件的匹配文件夾都應該省略。

3)這裏我假設文件結構的深度是2,即文件夾不會再包含文件夾。

所以,對於上述方案,結果應該是

<Partition> 
    <Directories> 
    <Directory> 
     <name>folder1</name> 
     <Unix-File> 
     <name>file1</name> 
     </Unix-File> 
    </Directory> 
    </Directories> 
</Partition> 

我使用下面的XSL文件。

<xsl:if test="count(Drive/Folders/Folder) > 0"> 
    <Directories> 
    <xsl:for-each select="Partition/Directories/Directory"> 
     <xsl:variable name="directoryName" select="name"/> 
     <xsl:if test="../../../Drive/Folders/Folder[name=$directoryName]"> 
     <Directory> 
      <name><xsl:value-of select="name"/> 
      </name> 
      <Unix-Files> 
      <xsl:for-each select="Unix-Files/Unix-File"> 
       <xsl:variable name="fileName" select="name"/> 
       <xsl:if test="../../../../../Drive/Folders/Folder[name=$directoryName]/Files/File[name=$fileName]"> 
       <xsl:if test="../../../../../Drive/Folders/Folder[name=$directoryName]/Files/File[name=$fileName]/State != 'Writable'"> 
        <xsl:value-of select="."/> 
       </xsl:if> 
       </xsl:if> 
      </xsl:for-each> 
      </Unix-Files> 
     </Directory> 
     </xsl:if> 
    </xsl:for-each> 
    </Directories> 
</xsl:if> 

上面的XSLT工作正常,除了上面的要求2。即文件夾中的文件不匹配時,也應該省略文件夾。

回答

1

你可以給這個鍵基礎的解決方案一試:

<?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"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="kFile" match="Files/File[State='Writable']" use="concat(../../name, '/' , name)"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy > 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="Directory"> 
     <xsl:if test="Unix-File[ key('kFile', concat(../name, '/', name))]"> 
      <xsl:apply-templates select="name"/> 
      <xsl:copy> 
       <xsl:for-each select="Unix-File[ key('kFile', concat(../name, '/', name))]" > 
        <xsl:apply-templates select="."/> 
       </xsl:for-each> 
       </xsl:copy> 
     </xsl:if> 
    </xsl:template> 

    <xsl:template match="/*" > 
     <Partition> 
      <xsl:if test="count(Drive/Folders/Folder) > 0"> 
       <xsl:element name="Directories" > 
        <xsl:apply-templates select="Partition/Directories/Directory" /> 
       </xsl:element> 
      </xsl:if> 
     </Partition> 
    </xsl:template> 

</xsl:stylesheet> 

有了這個輸入:

<?xml version="1.0" encoding="utf-8" ?> 
<xml> 
    <Drive> 
     <Folders> 
      <Folder> 
       <name>folder1</name> 
       <Files> 
        <File> 
         <State>Writable</State> 
         <name>file1</name> 
        </File> 
       </Files> 
      </Folder> 
     </Folders> 
     <Files> 
      <File> 
       <State>Readable</State> 
       <name>file2</name> 
      </File> 
     </Files> 
    </Drive> 
    <Partition> 
     <Directories> 
      <Directory> 
       <name>folder1</name> 
       <Unix-File> 
        <name>file1</name> 
       </Unix-File> 
      </Directory> 
      <Directory> 
       <name>folder-5</name> 
       <Unix-File> 
        <name>file-5</name> 
       </Unix-File> 
      </Directory> 
     </Directories> 
     <Unix-Files> 
      <Unix-File> 
       <name>file2</name> 
      </Unix-File> 
     </Unix-Files> 
    </Partition> 
</xml> 

它會生成以下的輸出:

<?xml version="1.0"?> 
<Partition> 
    <Directories> 
    <name>folder1</name> 
    <Directory> 
     <Unix-File> 
     <name>file1</name> 
     </Unix-File> 
    </Directory> 
    </Directories> 
</Partition> 

的關鍵「kFile 「以」[文件夾名稱]/[文件名]「的形式爲狀態可寫的每個文件保存條目。
目錄模板檢查本目錄中是否有任何Unix文件的kFile鍵。

+0

非常好。完全符合我的要求。 – user1793318