2013-10-24 65 views
2

我有一些代碼將兩個XML文檔的屬性差異(僅更新,不是新的屬性節點)進行比較,並生成一組指向屬性的XPath指針,屬性的新值。將XSLT更新爲僅給出新值並將XPath更新爲屬性

的設置

例如,給定一個老XML和新的XML:

舊XML

<EntityA> 
    <EntityB id="foo1" value="bar1" ignoredbutsave="bazz1"/> 
</EntityA> 

新的XML

<EntityA> 
    <EntityB id="foo2" value="bar2"/> 
</EntityA> 

我的代碼將返回

/EntityA/EntityB/@id, foo2 
/EntityA/EntityB/@value, bar2 

我想生成合並舊XML到新的XML的XSLT,創建以下XML:

<EntityA> 
    <EntityB id="foo2" value="bar2" ignoredbutsave="bazz1"/> 
</EntityA> 

所有答案,我發現上SO假設一些關於屬性名稱的先驗知識。在這種情況下,我只給出了XPath引用的屬性,而不是名稱本身。我知道我可以解析XPath字符串來派生屬性名稱,但寧願保持代碼中的複雜性。

我已經試過

,因爲我需要的ignoredbutsave屬性從舊的XML複製我不能使用attribute value template。我試圖用一個xsl:PARAM從XPath的選擇屬性名稱和XSL中使用它:屬性,像這樣:

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

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

    <xsl:template match="/EntityA/EntityB/@id"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     <xsl:param name="newValue" select="name(/EntityA/EntityB/@id)"/> 
     <xsl:attribute name="$newValue">newAttributeId</xsl:attribute> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/EntityA/EntityB/@value"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     <xsl:param name="myattrname" select="name(/EntityA/EntityB/@value)"/> 
     <xsl:attribute name="$myattrname">newAttributeValue</xsl:attribute> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

然而,這將導致錯誤The value '$myattrname' of the attribute 'name' is not a valid QName.

所以,問題是給定了屬性的XPath和該屬性的新值,如何生成更新該值而不明確引用屬性名稱的XSLT?

+0

你有沒有嘗試把'$ myattrname'放在花括號裏? –

+0

@MarcusRickert - yes''確實有效。 – lreeder

回答

1

這XSLT轉換:

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

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

    <xsl:template match="/EntityA/EntityB/@id"> 
    <xsl:attribute name="{name()}">foo2</xsl:attribute> 
    </xsl:template> 

    <xsl:template match="/EntityA/EntityB/@value"> 
    <xsl:attribute name="{name()}">bar2</xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

適用於舊的XML:

<EntityA> 
    <EntityB id="foo1" value="bar1" ignoredbutsave="bazz1"/> 
</EntityA> 

息率舊XML與製造所需的屬性值替換:

<EntityA> 
    <EntityB id="foo2" value="bar2" ignoredbutsave="bazz1"/> 
</EntityA> 
+0

謝謝,kjhughes,做到了。 ' bar2'('name()'中沒有點)也可以。 – lreeder

+0

@lreeder,關於在'name()'中放入'.'的好建議。清潔器。答案已更新。 – kjhughes

+1

如果要在命名空間前綴屬性上工作,則可能需要修改該答案。 –