有人可以帮助我解决以下问题,这里是输入XML,我正在使用的XSLT和预期的输出。实际上我知道这是因为没有生成唯一的generateid这个xslt无法生成所需的输出,但我不知道应该在哪里插入代码。
XML:
<item id="N65537" text="catalog">
<item id="N65540" text="cd">
<item id="N65542" text="title">
<item id="N65543" img="VAL" text="Empire Burlesque" />
</item>
<item id="N65545" text="artist">
<item id="N65546" img="VAL" text="Bob Dylan" />
</item>
<item id="N65548" text="country">
<item id="N65549" text="attr1" img="ATTR">
<item id="N65549_N65549" text="primary" img="ATTRVAL" />
</item>
<item id="N65550" img="VAL" text="USA" />
</item>
<item id="N65552" text="company">
<item id="N65553" text="attr2" img="ATTR">
<item id="N65553_N65553" text="main" img="ATTRVAL" />
</item>
<item id="N65554" img="VAL" text="Columbia" />
</item>
<item id="N65556" text="price">
<item id="N65557" img="VAL" text="10.90" />
</item>
<item id="N65559" text="year">
<item id="N65560" img="VAL" text="1985" />
</item>
</item>
<item id="N65563" text="cd">
<item id="N65565" text="title">
<item id="N65566" img="VAL" text="Hide your heart" />
</item>
<item id="N65568" text="artist">
<item id="N65569" img="VAL" text="Bonnie Tyler" />
</item>
<item id="N65571" text="country">
<item id="N65572" img="VAL" text="UK" />
</item>
<item id="N65574" text="company">
<item id="N65575" img="VAL" text="CBS Records" />
</item>
<item id="N65577" text="price">
<item id="N65578" img="VAL" text="9.90" />
</item>
<item id="N65580" text="year">
<item id="N65581" img="VAL" text="1988" />
</item>
</item>
</item>
XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:call-template name="dispatch">
<xsl:with-param name="nodes" select="node()"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="dispatch">
<xsl:param name="nodes"/>
<xsl:choose>
<xsl:when test="text()">
<xsl:call-template name="apply" >
<xsl:with-param name="select" select="node()" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="apply" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="apply">
<xsl:param name="select" select="node()" />
<xsl:for-each select="$select">
<xsl:if test='local-name() !=""'>
<xsl:variable name="ename">
<xsl:for-each select="@*">
<xsl:if test='name()="img1"'>
<xsl:text><xsl:value-of select="." /></xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="aname">
<xsl:for-each select="@*">
<xsl:if test='name()="img"'>
<xsl:text><xsl:value-of select="." /></xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="@*">
<xsl:variable name="tname">
<xsl:text><xsl:value-of select="." /></xsl:text>
</xsl:variable>
<xsl:choose>
<xsl:when test='name() ="text" and normalize-space($ename) = "VAL" and normalize-space($aname) != "ATTR"'>
<xsl:element name="{$tname}">
<xsl:for-each select="$select">
<xsl:call-template name="dispatch"/>
</xsl:for-each>
</xsl:element>
</xsl:when>
<xsl:when test='name() ="text" and normalize-space($ename) = "VAL" '>
<xsl:value-of select="$tname" />
</xsl:when>
<xsl:when test='name() ="text" and normalize-space($aname) = "ATTR"'>
<xsl:attribute name="id"><xsl:value-of select="$aname" /></xsl:attribute>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
预期产出:
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country attr1="primary">USA</country>
<company attr2="main">Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
答案 0 :(得分:3)
编辑:在问题中添加了详细信息后修改后的答案。
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- normal items become an ordinary element -->
<xsl:template match="item">
<xsl:element name="{@text}">
<!-- attributes must be created before any other contents -->
<xsl:apply-templates select="item[@img='ATTR']" />
<!-- now process sub-elements and values (i.e. "anything else") -->
<xsl:apply-templates select="item[not(@img='ATTR')]" />
</xsl:element>
</xsl:template>
<!-- items with "ATTR" become an attribute -->
<xsl:template match="item[@img='ATTR']">
<xsl:attribute name="{@text}">
<xsl:value-of select="item[@img='ATTRVAL']/@text" />
</xsl:attribute>
</xsl:template>
<!-- items with "VAL" become a simple text -->
<xsl:template match="item[@img='VAL']">
<xsl:value-of select="@text" />
</xsl:template>
</xsl:stylesheet>
给出
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country attr1="primary">USA</country>
<company attr2="main">Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
样式表之所以有效,是因为XSL处理器根据匹配表达式的特殊性选择模板。 match="item[@img='ATTR']"
比match="item"
更具体,因此对于每个<item>
已处理(通过<xsl:apply-templates select="item" />
),引擎会自动选择正确的模板。
答案 1 :(得分:1)
我在XSLT解决方案中看到的主要问题是您使用xsl:if和xsl:choose而不是'select'来过滤节点。这使得您的XSLT难以阅读和理解(至少对我而言)。
试试这个:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes"/>
<xsl:template match="/item[@text='catalog']">
<catalog>
<xsl:apply-templates select="item[@text='cd']"></xsl:apply-templates>
</catalog>
</xsl:template>
<xsl:template match="item[@text='cd']">
<cd>
<title><xsl:value-of select="item[@text='title']/item[@img1='VAL']/@text"/></title>
<artist><xsl:value-of select="item[@text='artist']/item[@img1='VAL']/@text"/></artist>
<country><xsl:value-of select="item[@text='country']/item[@img1='VAL']/@text"/></country>
<company><xsl:value-of select="item[@text='company']/item[@img1='VAL']/@text"/></company>
<price><xsl:value-of select="item[@text='price']/item[@img1='VAL']/@text"/></price>
<year><xsl:value-of select="item[@text='year']/item[@img1='VAL']/@text"/></year>
</cd>
</xsl:template>
</xsl:stylesheet>
解决方案不包括ATTR节点,因为它们不是描述结果的一部分。
答案 2 :(得分:0)
如果您可以更改输入xml,请执行此操作。 XML应该在标签名称和结构中带有一些含义。调用所有内容item
只会使其无法读取。
进行这样的更改还允许您编写不依赖于节点层次结构选择器技巧的可读XSLT。
答案 3 :(得分:0)
这个怎么样:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<catalog>
<xsl:for-each select="/item[@text='catalog']/item[@text='cd']">
<cd>
<xsl:for-each select="item">
<xsl:variable name="ename" select="string(@text)"/>
<xsl:variable name="value" select="item/@text"/>
<xsl:element name="{$ename}">
<xsl:value-of select="$value"/>
</xsl:element>
</xsl:for-each>
</cd>
</xsl:for-each>
</catalog>
</xsl:template>
</xsl:stylesheet>
不如Tomalaks解决方案好 - 但可能对意图略显清晰。