我正在将相同的多标签元素转换为不同的记录。 在这我使用的是XSLT。 我需要XSLT的帮助。 我得到第一个标签结果是正确的,坚果idont知道为什么第二个标签没有得到。
说明:: * 在第一张CD中::单个atrist到多个标题。我想根据标题将其拆分为不同的标签。 在第二张CD ::第一个艺术家的第一个标题和第二个艺术家的第二个标题。我也需要基于标题和艺术家的不同(两个)CD标签。[第一个标题第一个艺术家和第二个标题 - 第二个标题]。 *
My Source XML就像以下::
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
<cd>
<title>Burlesque</title>
<title>Empire</title>
<title>Emp</title>
<title>Em</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your</title>
<title>heart</title>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title/>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
</catalog>
XSLT ::
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:key name="k" match="title" use="text()"/>
<xsl:key name="l" match="artist" use="text()"/>
<xsl:template match="/">
<catalog>
<xsl:apply-templates select="//cd/title | artist[not(node() = preceding-sibling::node())]"/>
</catalog>
</xsl:template>
<xsl:template match="//cd">
<xsl:param name="title" select="title"/>
<xsl:param name="artist" select="artist"/>
<cd>
<xsl:copy-of select="key('k', $title)[not(node() = preceding-sibling::node())]"/>
<xsl:copy-of select="key('l', $artist)[not(node() = preceding-sibling::node())]"/>
<xsl:copy-of select="./*[name() != 'title' and 'artist']"/>
</cd>
</xsl:template>
<xsl:template match="title">
<xsl:apply-templates select="..">
<xsl:with-param name="title" select="."/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
我得到的是什么::
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<cd>
<title>Burlesque</title>
<artist>Bob Dylan</artist>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Empire</title>
<artist>Bob Dylan</artist>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Emp</title>
<artist>Bob Dylan</artist>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Em</title>
<artist>Bob Dylan</artist>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your</title>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>heart</title>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<artist>Dolly Parton</artist>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
</catalog>
我需要什么::
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<cd>
<title>Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Empire</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Emp</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Em</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your</title>
<artist>Bonnie</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>heart</title>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<artist>Dolly Parton</artist>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
</catalog>
任何人都能帮助我吗???
答案 0 :(得分:1)
这是"generic XML shredding" transformation 的应用程序,其中参数设置为所需的叶节点,并进行较小的后处理以从结果中删除两个顶部包装节点重新涡卷:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pLeafNodes" select="/*/*/title"/>
<xsl:template match="/">
<xsl:variable name="vrtfResult">
<xsl:call-template name="StructRepro"/>
</xsl:variable>
<catalog>
<xsl:copy-of select="ext:node-set($vrtfResult)/catalog/node()"/>
</catalog>
</xsl:template>
<xsl:template name="StructRepro">
<xsl:param name="pLeaves" select="$pLeafNodes"/>
<xsl:for-each select="$pLeaves">
<xsl:apply-templates mode="build" select="/*">
<xsl:with-param name="pChild" select="."/>
<xsl:with-param name="pLeaves" select="$pLeaves"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template mode="build" match="node()|@*">
<xsl:param name="pChild"/>
<xsl:param name="pLeaves"/>
<xsl:copy>
<xsl:apply-templates mode="build" select="@*"/>
<xsl:variable name="vLeafChild" select=
"*[count(.|$pChild) = count($pChild)]"/>
<xsl:choose>
<xsl:when test="$vLeafChild">
<xsl:apply-templates mode="build"
select="$vLeafChild
|
node()[not(count(.|$pLeaves) = count($pLeaves))]">
<xsl:with-param name="pChild" select="$pChild"/>
<xsl:with-param name="pLeaves" select="$pLeaves"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="build" select=
"node()[not(.//*[count(.|$pLeaves) = count($pLeaves)])
or
.//*[count(.|$pChild) = count($pChild)]
]
">
<xsl:with-param name="pChild" select="$pChild"/>
<xsl:with-param name="pLeaves" select="$pLeaves"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<catalog>
<cd>
<title>Burlesque</title>
<title>Empire</title>
<title>Emp</title>
<title>Em</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your</title>
<title>heart</title>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title/>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
</catalog>
产生了想要的正确结果:
<catalog>
<cd>
<title>Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Empire</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Emp</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Em</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your</title>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>heart</title>
<artist>Bonnie</artist>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title/>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
</catalog>
更新:OP已经改变了他的问题,并且他要求对于有多个艺术家的CD,应该有艺术家的额外分割。
这是解决方案 - 它是一个双程处理。在第一次传递中,文档将转换为catalog
,其中每个cd
都有一个artist
。然后第二遍就是我上面给出的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates mode="pass1"/>
</xsl:variable>
<xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)"/>
<xsl:variable name="pLeafNodes" select="$vPass1/*/*/title"/>
<xsl:variable name="vrtfResult">
<xsl:call-template name="StructRepro">
<xsl:with-param name="pLeaves" select="$pLeafNodes"/>
</xsl:call-template>
</xsl:variable>
<catalog>
<xsl:copy-of select="ext:node-set($vrtfResult)/catalog/node()"/>
</catalog>
</xsl:template>
<xsl:template name="StructRepro">
<xsl:param name="pLeaves"/>
<xsl:variable name="vDoc" select=
"$pLeaves[1]/ancestor::node()[last()]"/>
<xsl:for-each select="$pLeaves">
<xsl:apply-templates mode="build" select="$vDoc/*">
<xsl:with-param name="pChild" select="."/>
<xsl:with-param name="pLeaves" select="$pLeaves"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template mode="build" match="node()|@*">
<xsl:param name="pChild"/>
<xsl:param name="pLeaves"/>
<xsl:copy>
<xsl:apply-templates mode="build" select="@*"/>
<xsl:variable name="vLeafChild" select=
"*[count(.|$pChild) = count($pChild)]"/>
<xsl:choose>
<xsl:when test="$vLeafChild">
<xsl:apply-templates mode="build"
select="$vLeafChild
|
node()[not(count(.|$pLeaves) = count($pLeaves))]">
<xsl:with-param name="pChild" select="$pChild"/>
<xsl:with-param name="pLeaves" select="$pLeaves"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="build" select=
"node()[not(.//*[count(.|$pLeaves) = count($pLeaves)])
or
.//*[count(.|$pChild) = count($pChild)]
]
">
<xsl:with-param name="pChild" select="$pChild"/>
<xsl:with-param name="pLeaves" select="$pLeaves"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
<xsl:template match="node()|@*" mode="pass1">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="pass1"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cd[artist[2]]" mode="pass1">
<xsl:for-each select="artist">
<xsl:apply-templates select=".." mode="singleArtist">
<xsl:with-param name="pArtistPos" select="position()"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="cd" mode="singleArtist">
<xsl:param name="pArtistPos"/>
<cd>
<xsl:apply-templates mode="pass1" select=
"title[position() = $pArtistPos]"/>
<xsl:apply-templates mode="pass1" select=
"artist[position() = $pArtistPos]"/>
<xsl:apply-templates mode="pass1" select=
"node()[not(self::title or self::artist)]"/>
</cd>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
当此转换应用于同一XML文档(上图)时,结果现在满足其他要求:
<catalog>
<cd>
<title>Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Empire</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Emp</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Em</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your</title>
<artist>Bonnie</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>heart</title>
<artist> Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title/>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
</catalog>