2014-05-23 48 views
2

所以我有以下格式的XML文件:移動通過XSLT從一個XML文件屬性到另一個

[...] 
<level1> 
    <para id="1"/> 
    <image type="photo" artist="Joe"/> 
    <para id="2"/> 
    <para id="3"/> 
    <level2> 
     <para id="4"/> 
     <image type="pencil" artist="Bob"/> 
     <para id="5"/> 
    </level2> 
    <para id="6"/> 
    <image type="oil" artist="Joe"/> 
</level1> 
[...] 

的問題是,在圖像屬性並不總是正確的,他們沒有唯一的標識符。我有另一個具有所有正確屬性的文件。我試圖編寫一個將刪除不正確屬性的轉換,然後從我的其他文件中放置正確的屬性。

這是我到目前爲止有:

<xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <!-- ============================================================= --> 
    <xsl:variable name="target" select="document('correct.xml')//image"/> 


    <xsl:template match="image"> 
     <xsl:variable name="vPath1"> 
      <xsl:for-each select="ancestor-or-self::*"> 
       <xsl:value-of select="concat('/',name())"/> 
      </xsl:for-each> 
     </xsl:variable> 
     <xsl:variable name="vPath2"> 
      <xsl:for-each select="$target[ancestor-or-self::*]"> 
       <xsl:value-of select="concat('/',name())"/> 
      </xsl:for-each> 
     </xsl:variable> 
     <xsl:copy> 
      <xsl:if test="$vPath1=$vPath2"> 
       <xsl:copy-of select="$target/@*"/> 
      </xsl:if> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

這成功地刪除所有我的不正確的屬性,但它並沒有將正確的。這似乎是我的'如果'的聲明從來沒有打,但我知道路徑是相同的。我做錯了什麼?

我correct.xml看起來是這樣的(這也是輸出應該是什麼樣子):

[...] 
<level1> 
    <para id="1"/> 
    <image type="pencil" artist="Joe"/> 
    <para id="2"/> 
    <para id="3"/> 
    <level2> 
     <para id="4"/> 
     <image type="photo" artist="Steve"/> 
     <para id="5"/> 
    </level2> 
    <para id="6"/> 
    <image type="oil" artist="Bob"/> 
</level1> 
    [...] 
+0

您驗證了'$ vPath1 = $ vPath2'與''etc? –

+0

我對xslts還是很缺乏經驗,所以我沒有那樣做。我試了一下,我的$ vPath1沒問題,但是我的$ vPath2只是返回'figure/figure/figure/...' 任何想法在設置變量時出錯了? – Beeblebrox42

+0

您使用的是XSL 1.0還是2.0? –

回答

1

如果2個XML文檔的結構完全一致,可以搭配使用位置謂詞的路徑。這將確保您比較獨特的路徑。

否則,你必須匹配id或其他東西。如果是這樣的話,讓我知道,我可以更新我的答案,在生成路徑時使用id(或其他)屬性。

XML輸入

<level1> 
    <para id="1"/> 
    <image type="photo" artist="Joe"/> 
    <para id="2"/> 
    <para id="3"/> 
    <level2> 
     <para id="4"/> 
     <image type="pencil" artist="Bob"/> 
     <para id="5"/> 
    </level2> 
    <para id="6"/> 
    <image type="oil" artist="Joe"/> 
</level1> 

正確的XML(我把它命名爲so_good.xml。)

<level1> 
    <para id="1"/> 
    <image type="pencil" artist="Joe"/> 
    <para id="2"/> 
    <para id="3"/> 
    <level2> 
     <para id="4"/> 
     <image type="photo" artist="Steve"/> 
     <para id="5"/> 
    </level2> 
    <para id="6"/> 
    <image type="oil" artist="Bob"/> 
</level1> 

XSLT 2.0(也可以作爲1.0)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="good" select="document('so_good.xml')"/> 

    <xsl:template name="getPath"> 
     <xsl:for-each select="ancestor-or-self::*"> 
      <xsl:value-of select="concat('/',local-name())"/> 
      <!--Predicate is only output when needed.--> 
      <xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]"> 
       <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

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

    <xsl:template match="image"> 
     <xsl:variable name="currPath"> 
      <xsl:call-template name="getPath"/> 
     </xsl:variable> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:apply-templates select="$good//image" mode="new-attrs"> 
       <xsl:with-param name="currPath" select="$currPath"/> 
      </xsl:apply-templates> 
      <xsl:apply-templates select="node()"/> 
     </xsl:copy>   
    </xsl:template> 

    <xsl:template match="image" mode="new-attrs"> 
     <xsl:param name="currPath"/> 
     <xsl:variable name="goodPath"> 
      <xsl:call-template name="getPath"/> 
     </xsl:variable> 
     <xsl:if test="$currPath=$goodPath"> 
      <xsl:copy-of select="@*"/> 
     </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 

XML輸出

<level1> 
    <para id="1"/> 
    <image type="pencil" artist="Joe"/> 
    <para id="2"/> 
    <para id="3"/> 
    <level2> 
     <para id="4"/> 
     <image type="photo" artist="Steve"/> 
     <para id="5"/> 
    </level2> 
    <para id="6"/> 
    <image type="oil" artist="Bob"/> 
</level1> 

爲了展示什麼東西被比較,你可以將此xsl:message添加到 「新ATTRS」 moded 「圖像」 模板:

<xsl:message>Comparing "<xsl:value-of select="$currPath"/>" (currPath) to "<xsl:value-of select="$goodPath"/>" (goodPath). Do they match? <xsl:value-of select="boolean($currPath=$goodPath)"/></xsl:message> 

你應該看到這樣的消息: (遺憾的圖像)

enter image description here

+0

太棒了!謝謝!我將不得不花費一些時間來弄清楚這是做什麼,但它的工作。 – Beeblebrox42

+0

@ Beeblebrox42 - 你非常歡迎。如果您有任何問題,請告訴我。 –

相關問題