下一个问题:我有“InputDoc”xml文件和xslt文件,以便转换成其他“OutputDoc”xml文档。 您可以在下面找到示例xslt和xml文档。
<?xml version="1.0" encoding="UTF-8"?>
<InputDoc>
<InputCollection>
<InputItem>
<InputValue>Value_1</InputValue>
</InputItem>
</InputCollection>
</InputDoc>
<?xml version="1.0" encoding="utf-16"?>
<OutputDoc>
<OutputElement>
<OutputItem>
<OutputValue>Value_1</OutputValue>
</OutputItem>
<OutputDescription>Description_1</OutputDescription>
</OutputElement>
</OutputDoc>
<?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 method="xml" indent="yes"/>
<xsl:template match="//InputCollection">
<OutputDoc>
<xsl:for-each select="InputItem">
<OutputElement>
<OutputItem>
<OutputValue><xsl:value-of select="InputValue" /></OutputValue>
</OutputItem>
<OutputDescription>
<xsl:call-template name="InputValue2OutputDescriptionMappings">
<xsl:with-param name="InputValueParam" select="InputValue" />
</xsl:call-template>
</OutputDescription>
</OutputElement>
</xsl:for-each>
</OutputDoc>
</xsl:template>
<xsl:template name="InputValue2OutputDescriptionMappings">
<xsl:param name="InputValueParam" />
<xsl:choose>
<xsl:when test="$InputValueParam='Value_1'">Description_1</xsl:when>
<xsl:when test="$InputValueParam='Value_2'">Description_2</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
有效。但是如果输出xml文档只包含“OutputElement”节点并且包含“InputValue2OutputDescriptionMappings”中的值,即如果“OutputDescription”节点的值为空,那么“OutputElement”节点将不会包含在“OutputDoc”中。
我如何使用上面的XSL转换呢?
答案 0 :(得分:1)
您必须首先获得映射的结果,然后将其测试为空并省略<OutputDescription>
标记,如:
<?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 method="xml" indent="yes"/>
<xsl:template match="//InputCollection">
<OutputDoc>
<xsl:for-each select="InputItem">
<OutputElement>
<OutputItem>
<OutputValue><xsl:value-of select="InputValue" /></OutputValue>
</OutputItem>
<xsl:variable name="desc">
<xsl:call-template name="InputValue2OutputDescriptionMappings">
<xsl:with-param name="InputValueParam" select="InputValue" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="string-length($desc/text())">
<OutputDescription><xsl:value-of select="$desc"/></OutputDescription>
</xsl:if>
</OutputElement>
</xsl:for-each>
</OutputDoc>
</xsl:template>
<xsl:template name="InputValue2OutputDescriptionMappings">
<xsl:param name="InputValueParam" />
<xsl:choose>
<xsl:when test="$InputValueParam='Value_1'">Description_1</xsl:when>
<xsl:when test="$InputValueParam='Value_2'">Description_2</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
但是,这里有一个更多的XSL版本,它将映射存储在一个变量中以省去映射模板,并使用“推送”处理(apply-templates)而不是“拉”处理。
<?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 method="xml" indent="yes"/>
<xsl:template match="//InputCollection">
<OutputDoc>
<xsl:apply-templates select="InputItem"/>
</OutputDoc>
</xsl:template>
<xsl:variable name="mapping">
<map input="Value_1" output="Description_1"/>
<map input="Value_2" output="Description_2"/>
</xsl:variable>
<xsl:template match="InputItem">
<OutputElement>
<OutputItem>
<OutputValue><xsl:value-of select="InputValue" /></OutputValue>
</OutputItem>
<xsl:variable name="input" select="InputValue/text()"/>
<xsl:variable name="desc" select="$mapping/map[@input=$input]/@output"/>
<xsl:if test="$desc">
<OutputDescription><xsl:value-of select="$desc"/></OutputDescription>
</xsl:if>
</OutputElement>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这是使用key()
优化的标准XSLT 1.0样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="description" match="description" use="@value"/>
<xsl:variable name="map">
<description value="Value_1">Description_1</description>
<description value="Value_2">Description_2</description>
</xsl:variable>
<xsl:template match="InputDoc">
<OutputDoc>
<xsl:apply-templates/>
</OutputDoc>
</xsl:template>
<xsl:template match="InputCollection">
<xsl:variable name="me" select="."/>
<xsl:for-each select="document('')">
<xsl:if test="key('description',$me/InputItem/InputValue)">
<OutputElement>
<xsl:apply-templates select="$me/*"/>
<xsl:apply-templates select="key('description',$me/InputItem/InputValue)"/>
</OutputElement>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="InputItem">
<OutputItem>
<xsl:apply-templates/>
</OutputItem>
</xsl:template>
<xsl:template match="InputValue">
<OutputValue>
<xsl:apply-templates/>
</OutputValue>
</xsl:template>
<xsl:template match="description">
<OutputDescription>
<xsl:apply-templates/>
</OutputDescription>
</xsl:template>
</xsl:stylesheet>
结果:
<OutputDoc>
<OutputElement>
<OutputItem>
<OutputValue>Value_1</OutputValue>
</OutputItem>
<OutputDescription>Description_1</OutputDescription>
</OutputElement>
</OutputDoc>
注意:“模式匹配”。 key()
包含多个文档(本例中为样式表)。
修改:对于非匹配值请求错过了条OutputElement
,抱歉。
现在,这个输入:
<InputDoc>
<InputCollection>
<InputItem>
<InputValue>Value_3</InputValue>
</InputItem>
</InputCollection>
</InputDoc>
输出:
<OutputDoc></OutputDoc>
注意:这是所有模板驱动的。因此,您甚至可以将更多逻辑应用于description
内容。