我有一个XML文件。
<?xml version="1.0" encoding="UTF-8"?>
<XML>
<Items>
<ItemRef ID='answer'></ItemRef>
<ItemRef ID='number'></ItemRef>
<ItemRef ID='delete'></ItemRef>
<ItemRef ID='remove'></ItemRef>
</Items>
<ItemDef ID='anwser'></ItemDef>
<ItemDef ID='number'>
<EnumItemRef EID = '1'></EnumItemRef>
</ItemDef>
<ItemDef ID='delete'>
<EnumItemRef EID = '2'></EnumItemRef>
</ItemDef>
<ItemDef ID='remove'></ItemDef>
<EnumItem EID="1">
<EnumItem Value = '1'></EnumItem>
<EnumItem Value = '2'></EnumItem>
<EnumItem Value = '3'></EnumItem>
</EnumItem>
<EnumItem EID="2">
<EnumItem Value = 'yes'></EnumItem>
<EnumItem Value = 'no'></EnumItem>
</EnumItem>
</XML>
我需要转换成这样的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<XML>
<Items>
<ItemRef ID='newid_answer'></ItemRef>
<ItemRef ID='newid_number'></ItemRef>
</Items>
<ItemDef ID='newid_answer'></ItemDef>
<ItemDef ID='newid_number'>
<EnumItemRef EID = '1'></EnumItemRef>
</ItemDef>
<EnumItem EID="1">
<EnumItem Value = '1'></EnumItem>
<EnumItem Value = '2'></EnumItem>
<EnumItem Value = '3'></EnumItem>
</EnumItem>
</XML>
我有以下XSLT 1.0文件。有了这个我能够创建我想要的Items和ItemDefs。我只是错过了如何找到相应的EnumItemRef和EnumItem的想法。我要检查当前的ItemDef是否有一个名为EnumItemRef的子项,或者我可以用一个关键函数来解决它(这可能是更好的解决方案)。我试过了两个,但我无法让它发挥作用。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:variable name="Items">
<Item ID="answer">newid_answer</Item>
<Item ID="number">newid_number</Item>
</xsl:variable>
<xsl:key name="get_Enum_by_ID" match="/XML/ItemDef/EnumItemRef" use="/XML/ItemDef/@ID" />
<xsl:template match="XML">
<xsl:copy>
<xsl:apply-templates />
<xsl:call-template name="Items" />
<xsl:call-template name="ItemDef" />
</xsl:copy>
</xsl:template>
<xsl:template name="Items">
<xsl:element name="Items">
<xsl:for-each select="exslt:node-set($Items)/Item">
<xsl:element name="ItemRef">
<xsl:attribute name="ID"><xsl:value-of select="text()"/></xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template name="ItemDef">
<xsl:for-each select="exslt:node-set($Items)/Item">
<xsl:element name="ItemDef">
<xsl:attribute name="ID"><xsl:value-of select="text()" /></xsl:attribute>
</xsl:element>
<-- how can I find the corresponding EnumitemRef and EnumItem? -->
<xsl:copy-of select="key('get_Enum_by_ID', @ID)" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
如果有人能告诉我如何解决这个问题,我会很高兴。
答案 0 :(得分:0)
虽然这并不简单,但我认为你使它变得比它需要的复杂得多。请尝试以下样式表(未经过彻底测试):
XSLT 1.0
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="Items">
<Item ID="answer">newid_answer</Item>
<Item ID="number">newid_number</Item>
</xsl:variable>
<xsl:key name="ItemDef-by-ID" match="ItemDef" use="@ID"/>
<xsl:key name="EnumItem-by-EID" match="EnumItem" use="@EID"/>
<xsl:variable name="xml" select="/"/>
<xsl:template match="/XML">
<xsl:copy>
<Items>
<xsl:copy-of select="$Items" />
</Items>
<xsl:apply-templates select="exsl:node-set($Items)/Item"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Item">
<xsl:variable name="item-id" select="@ID"/>
<xsl:variable name="EnumItemRef">
<xsl:for-each select="$xml">
<xsl:copy-of select="key('ItemDef-by-ID', $item-id)/EnumItemRef"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="EID" select="exsl:node-set($EnumItemRef)/EnumItemRef/@EID"/>
<ItemDef ID="{.}">
<xsl:copy-of select="$EnumItemRef"/>
</ItemDef>
<xsl:for-each select="$xml">
<xsl:copy-of select="key('EnumItem-by-EID', $EID)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
注意:当您处于由exslt:node-set()函数创建的节点集的上下文中时,您无法使用key()来查找源XML文档中的数据,除非您首先将上下文切换到源文档。