Xml XSLT-基于映射从模板中选择节点
这是我为解释而编写的xml内容示例Xml XSLT-基于映射从模板中选择节点,xml,xslt,xslt-2.0,Xml,Xslt,Xslt 2.0,这是我为解释而编写的xml内容示例 <doc> <array> <?Table_type Small?> <table> <data>text</data> </table> </array> <array> <?Table_type Medium?>
<doc>
<array>
<?Table_type Small?>
<table>
<data>text</data>
</table>
</array>
<array>
<?Table_type Medium?>
<table>
<data>text</data>
</table>
</array>
<array>
<?Table_type Large?>
<table>
<data>text</data>
</table>
</array>
</doc>
但它不会从映射中读取相应的属性值并将其放置在相应的
节点中
我的预期产出是
<doc>
<array>
<?Table_type Small?>
<table>
<data size="10">text</data>
</table>
</array>
<array>
<?Table_type Medium?>
<table>
<data size="20">text</data>
</table>
</array>
<array>
<?Table_type Large?>
<table>
<data size="30">text</data>
</table>
</array>
</doc>
文本
文本
文本
任何关于如何更改模板以从映射中读取正确值并向
节点添加正确属性的建议?您已经落入了陷阱,这是XSLT-1.0的一个严重问题
避免这种情况的一种方法是将
转换为XSLT文件中的数据岛。这个数据岛需要一个自己的名称空间,我称之为var
,它必须使用exclude result prefixes
指令从结果中明确排除
此外,我使用了两个变量来避免XML和XSLT名称空间之间的名称空间冲突
仅供参考:document(“”)/xsl:stylesheet
引用当前XSLT文档的XML根节点
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:var="some.var" exclude-result-prefixes="var">
<xsl:output method="xml" indent="yes" />
<var:tabletypemapping>
<map parent='Small' mapto='10'/>
<map parent='Medium' mapto='20'/>
<map parent='Large' mapto='30'/>
</var:tabletypemapping>
<xsl:template match="data">
<xsl:variable name="procIns" select="ancestor::array/processing-instruction('Table_type')" />
<xsl:variable name="mapIns" select="document('')/xsl:stylesheet/var:tabletypemapping/map[@parent = $procIns]/@mapto" />
<data size="{$mapIns}">
<xsl:apply-templates/>
</data>
</xsl:template>
<!-- Identity template left untouched -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出为:
<?xml version="1.0"?>
<doc>
<array>
<?Table_type Small?>
<table>
<data size="10">text</data>
</table>
</array>
<array>
<?Table_type Medium?>
<table>
<data size="20">text</data>
</table>
</array>
<array>
<?Table_type Large?>
<table>
<data size="30">text</data>
</table>
</array>
</doc>
文本
文本
文本
您已经落入了XSLT-1.0的一个严重问题的陷阱
避免这种情况的一种方法是将
转换为XSLT文件中的数据岛。这个数据岛需要一个自己的名称空间,我称之为var
,它必须使用exclude result prefixes
指令从结果中明确排除
此外,我使用了两个变量来避免XML和XSLT名称空间之间的名称空间冲突
仅供参考:document(“”)/xsl:stylesheet
引用当前XSLT文档的XML根节点
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:var="some.var" exclude-result-prefixes="var">
<xsl:output method="xml" indent="yes" />
<var:tabletypemapping>
<map parent='Small' mapto='10'/>
<map parent='Medium' mapto='20'/>
<map parent='Large' mapto='30'/>
</var:tabletypemapping>
<xsl:template match="data">
<xsl:variable name="procIns" select="ancestor::array/processing-instruction('Table_type')" />
<xsl:variable name="mapIns" select="document('')/xsl:stylesheet/var:tabletypemapping/map[@parent = $procIns]/@mapto" />
<data size="{$mapIns}">
<xsl:apply-templates/>
</data>
</xsl:template>
<!-- Identity template left untouched -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出为:
<?xml version="1.0"?>
<doc>
<array>
<?Table_type Small?>
<table>
<data size="10">text</data>
</table>
</array>
<array>
<?Table_type Medium?>
<table>
<data size="20">text</data>
</table>
</array>
<array>
<?Table_type Large?>
<table>
<data size="30">text</data>
</table>
</array>
</doc>
文本
文本
文本
您可能不需要在匹配本身中使用复杂的xpath表达式,尤其是在所有数据
元素前面都有有效的处理指令的情况下
主要问题是AVT用于计算size
属性。它正在寻找映射
元素的祖先,而不是当前的数据
元素。应该是这个
<data size="{$table.type.mapping/map[@parent=current()/ancestor::array/processing-instruction('Table_type')]/@mapto}">
您可能不需要在匹配本身中使用复杂的xpath表达式,尤其是在所有
数据
元素前面都有有效的处理指令的情况下
主要问题是AVT用于计算size
属性。它正在寻找映射
元素的祖先,而不是当前的数据
元素。应该是这个
<data size="{$table.type.mapping/map[@parent=current()/ancestor::array/processing-instruction('Table_type')]/@mapto}">
通过使用键执行查找,可以非常方便(高效)地执行此操作: XSLT2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="table.type.mapping">
<map parent='Small' mapto='10'/>
<map parent='Medium' mapto='20'/>
<map parent='Large' mapto='30'/>
</xsl:variable>
<xsl:key name="size" match="map" use="@parent" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="data">
<data size="{key('size', ancestor::array/processing-instruction('Table_type'), $table.type.mapping)/@mapto}">
<xsl:apply-templates/>
</data>
</xsl:template>
</xsl:stylesheet>
通过使用键执行查找,可以非常方便(高效)地执行此操作: XSLT2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="table.type.mapping">
<map parent='Small' mapto='10'/>
<map parent='Medium' mapto='20'/>
<map parent='Large' mapto='30'/>
</xsl:variable>
<xsl:key name="size" match="map" use="@parent" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="data">
<data size="{key('size', ancestor::array/processing-instruction('Table_type'), $table.type.mapping)/@mapto}">
<xsl:apply-templates/>
</data>
</xsl:template>
</xsl:stylesheet>
这个问题被标记为XSLT 2.0。@michael.hor257k:你当然是对的。在发布我的答案后,我才意识到这一点。这个问题被标记为XSLT 2.0。@michael.hor257k:当然你是对的。我在发布我的答案后才意识到这一点。