2013-10-08 161 views
0

我是XSLT新手。 我正在嘗試更新ID爲25以下的XML格式的當前int值,並將其更新爲範圍爲1-25的唯一標識符。使用XSLT更新屬性

* MYXML *

<Root> 
<Properties> 
<Props></Props> 
<Input> 
</Input> 
<Profile InstanceID ="4" ObjectID="XYZ"> (no need to update these instanceID) 
<ELM_INT>Profile 1</ELM_INT> 
<Video **InstanceID="26"** ObjectID="ABC" Type="103"></Video> 
<Audio **InstanceID="1"** ObjectID="DEF" Type="103"></Audio> 
<Audio **InstanceID="27"** ObjectID="GHI" Type="103"></Audio>  
<Output ObjectID="JKL" Type="104" Type="25"></Output> 
</Profile> 
</Properties> 

<Properties> 
<Props></Props> 
<Input> 
</Input> 
<Profile InstanceID ="4" ObjectID="XYZ"> (no need to update these instanceID) 
<ELM_INT>Profile 1</ELM_INT> 
<Video **InstanceID="33"** ObjectID="MNO" Type="103"></Video> 
<Audio **InstanceID="25"** ObjectID="PQR" Type="103"></Audio> 
<Audio **InstanceID="2"** ObjectID="EFG" Type="103"></Audio>  
<Output ObjectID="HIJ" Type="104" Type="25"></Output> 
</Profile> 
</Properties> 
</Root> 

我的XSLT

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 

<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:template match="node()|@*"> 
<xsl:copy> 
<xsl:apply-templates select="node()|@*"/> 
</xsl:copy> 
</xsl:template> 

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

<!--Get all instance id's includng Profile and call loop--> 
<xsl:for-each select="@*/.."> 
<!--Id instanceId is greater than 25 than call loop--> 
<xsl:variable name="CurrentInstanceID"> 
<xsl:value-of select="@InstanceID"/> 
</xsl:variable> 


<xsl:if test="$CurrentInstanceID &gt; 25"> 
<!--<xsl:text> .Calling Iterate1To25 </xsl:text>--> 
<xsl:call-template name="Iterate1To25"> 
<xsl:with-param name="pStart" select="1"/> 
<xsl:with-param name="pEnd" select="25"/> 
</xsl:call-template> 
</xsl:if> 

</xsl:for-each> 

</xsl:template> 
<!--Main END--> 

<!-- Iterate1To25which iterate for 25 times START--> 
<xsl:template name="Iterate1To25" > 
<xsl:param name="pStart"/> 
<xsl:param name="pEnd"/> 

<xsl:if test="not($pStart &gt; $pEnd)"> 

<xsl:variable name="serchAudeoInstanceID"> 
<xsl:value-of select="count(../Audio[@InstanceID=$pStart])"/> 
</xsl:variable> 

<xsl:variable name="serchVideoInstanceID"> 
<xsl:value-of select="count(../Video[@InstanceID=$pStart])"/> 
</xsl:variable> 

<xsl:choose> 
<xsl:when test="$serchAudeoInstanceID &gt; 0 or $serchVideoInstanceID &gt; 0> 
<xsl:call-template name="Iterate1To25"> 
<xsl:with-param name="pStart" select="$pStart+1"/> 
<xsl:with-param name="pEnd" select="25"/> 
</xsl:call-template> 
</xsl:when> 
<xsl:otherwise> 
<!--pStart can be assigned--> 
<xsl:element name="Valid_ID"> 
<xsl:value-of select="$pStart"/> 
<xsl:attribute name="InstanceID"> 
<xsl:value-of select="$pStart"/> 
</xsl:attribute> 
</xsl:element> 

</xsl:otherwise> 
</xsl:choose> 

</xsl:if> 

</xsl:template> 

</xsl:stylesheet> 

輸出/轉換的XML

<Root> 
<Properties> 
<Props></Props> 
<Input> 
</Input> 
<Profile_InstanceID ="4" ObjectID="XYZ"> 
<ELM_INT>Profile 1</ELM_INT> 

<Video **InstanceID="26"** ObjectID="ABC" Type="103"></Video> 
****<ValidID>2</ValidID>**** 

<Audio **InstanceID="1"** ObjectID="DEF" Type="103"></Audio> 

<Audio **InstanceID="27"** ObjectID="GHI" Type="103"></Audio>  
****<ValidID>2</ValidID> (expected 3)**** 

<Output ObjectID="JKL" Type="104" Type="25"></Output> 
</Profile_Instance> 
</Properties> 

<Properties> 
<Props></Props> 
<InputTransport> 
</InputTransport> 
<Profile_InstanceID ="4" ObjectID="XYZ"> 
<ELM_INT>Profile 1</ELM_INT> 

<Video **InstanceID="33"** ObjectID="MNO" Type="103"></Video> 
****<ValidID>1</ValidID>**** 

<Audio **InstanceID="25"** ObjectID="PQR" Type="103"></Audio> 

<Audio **InstanceID="2"** ObjectID="EFG" Type="103"></Audio>  

<Output ObjectID="HIJ" Type="104" Type="25"></Output> 
</Profile_Instance> 
</Properties> 
</Root> 

查詢 1.如何更新屬性InstanceID而不是追加附加元素 2.如何跟蹤生成/分配/新生成的實例ID,以避免重複。

在此先感謝,任何幫助將是可觀的。

回答

1

你已經開始用身份模板的正確方式,但是我不明白你下一步要做什麼。你有這樣的:

match="Profile/*" 

但我沒有在您的源文件中看到名爲Profile的任何元素。我期望從你對問題的描述中看到的是這樣的:

<xsl:template match="@InstanceID[. > 25]"> 
    <xsl:attribute name="InstanceId" select="xxxx"/> 
</xsl:template> 

其中xxxx是屬性的新值;這是問題的下一部分。這不是特別容易,但你似乎有所有的邏輯來計算變量$ pstart,這似乎是你想要的值,所以只需使用它作爲xxxxx以上。

+0

嗨MK,謝謝你的回覆。 它的匹配=「Profile_InstanceID/*」,不匹配=「Profile/*」。 xml和xslt元素是修改的內容。 –

+0

您好MK,我試過這些方法,但編輯提示爲「選擇是'xsl:屬性'元素的無效屬性」 –

+0

它現在正在工作,但它更新所有instanceID具有相同的值。 –

0

讓我們嘗試解決分配唯一ID的問題。這個很難,而且很高興知道真正的要求是什麼,因爲它可能過於束縛。

我想用一個初始傳遞來確定正在使用的標識符,並生成一個包含可供免費使用的標識符的XML文檔。這並不難:基本上(在僞代碼中)「對於我在1到N中不存在(我在輸入中)返回i」。

然後,我會建立一個標識符需要改變的節點列表,把這個列表放入一個變量中;然後用該變量作爲參數對文檔進行樹狀漫步;當一個節點出現在列表中時,作爲列表中的第N個項目,將標識符替換爲「免費使用」列表中的第N個標識符。

我不會試圖用XSLT 1.0。但是,我不會嘗試用XSLT 1.0做任何事情;一旦你習慣了2.0,它就像努力工作一樣。另外,請不要問我是否將此算法轉換爲XSLT代碼;如果你不能自己做,你應該付錢給其他人爲你做。