0

我是 XSLT 的新手。我正在尝试将大于 25 的 XML 之后的 ID 当前 int 更新为 1-25 范围内的唯一 ID。

* 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 以避免重复。

在此先感谢,任何帮助将不胜感激。

4

2 回答 2

1

您已经使用身份模板以正确的方式开始,但是我不明白您接下来要做什么。你有这个:

match="Profile/*"

但我没有看到Profile您的源文档中命名的任何元素。我希望从您对问题的描述中看到如下内容:

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

其中 xxxx 是属性的新值;这就是问题的下一部分。这不是特别容易,但是您似乎拥有计算变量 $pstart 的所有逻辑,这似乎是您想要的值,因此只需将其用作上面的 xxxxx。

于 2013-10-08T22:54:04.313 回答
0

让我们尝试解决分配唯一 ID 的问题。这个是相当困难的,很高兴知道真正的需求是什么,因为它可能会受到过度约束。

我认为,我会从确定正在使用的标识符的初始通道开始,并生成一个包含可免费使用的标识符的 XML 文档。这并不太难:本质上(在伪代码中)“对于 i in 1 to N where not(i present in input) return i”。

然后我会建立一个需要更改标识符的节点列表,将这个列表放入一个变量中;然后使用此变量作为参数对文档进行树遍历;当一个节点出现在列表中时,作为列表中的第 N 个项目,将标识符替换为“免费使用”列表中的第 N 个标识符的 id。

我不会用 XSLT 1.0 来尝试这个。但是,我不会尝试用 XSLT 1.0 做任何事情。一旦你习惯了 2.0,这太像艰苦的工作了。另外,请不要让我把这个算法翻译成 XSLT 代码;如果你不能自己做,你应该付钱给别人为你做。

于 2013-10-09T22:55:09.020 回答