Xml 如何使用XSLT仅获取特定行和特定列?
如何使用XSLT转换此XML文件:Xml 如何使用XSLT仅获取特定行和特定列?,xml,xslt,Xml,Xslt,如何使用XSLT转换此XML文件: <file> <row> <cell></cell> <cell>(info...)</cell> <cell></cell> </row> <row> <cell>first name</cell> <cel
<file>
<row>
<cell></cell>
<cell>(info...)</cell>
<cell></cell>
</row>
<row>
<cell>first name</cell>
<cell>last name</cell>
<cell>age</cell>
</row>
<row>
<cell>Jim</cell>
<cell>Smith</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>Rogers</cell>
<cell>22</cell>
</row>
<row>
<cell>Hank</cell>
<cell>Grandier</cell>
<cell>23</cell>
</row>
<row>
<cell>(info...)</cell>
<cell></cell>
<cell>(info...)</cell>
</row>
<row>
<cell>Sally</cell>
<cell>Cloud</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>Randall</cell>
<cell>44</cell>
</row>
</file>
<file>
<row>
<cell>Jim</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>22</cell>
</row>
<row>
<cell>Sally</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>44</cell>
</row>
</file>
(信息…)
名字
姓
年龄
吉姆
史密斯
34
罗伊
罗杰斯
22
汉克
格朗迪耶
23
(信息…)
(信息…)
俏皮话
云彩
26
约翰
兰德尔
44
要创建此XML文件,请执行以下操作:
<file>
<row>
<cell></cell>
<cell>(info...)</cell>
<cell></cell>
</row>
<row>
<cell>first name</cell>
<cell>last name</cell>
<cell>age</cell>
</row>
<row>
<cell>Jim</cell>
<cell>Smith</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>Rogers</cell>
<cell>22</cell>
</row>
<row>
<cell>Hank</cell>
<cell>Grandier</cell>
<cell>23</cell>
</row>
<row>
<cell>(info...)</cell>
<cell></cell>
<cell>(info...)</cell>
</row>
<row>
<cell>Sally</cell>
<cell>Cloud</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>Randall</cell>
<cell>44</cell>
</row>
</file>
<file>
<row>
<cell>Jim</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>22</cell>
</row>
<row>
<cell>Sally</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>44</cell>
</row>
</file>
吉姆
34
罗伊
22
俏皮话
26
约翰
44
基本上规则是:
- 只有第一列和第三列(名字和年龄)
- 只有特定范围内的行,例如,在上面的简单示例中,它将是第3-5行和第7-8行,因此我假设我需要某种映射表,其中包含此信息
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />
<xsl:param name="range-1-begin" select="3"/>
<xsl:param name="range-1-end" select="4"/>
<xsl:param name="range-2-begin" select="6"/>
<xsl:param name="range-2-end" select="7"/>
<xsl:template match="file">
<marco>
<xsl:for-each select="row">
<xsl:if test="(position() >= $range-1-begin and position() <= $range-1-end)
or (position() >= $range-2-begin and position() <= $range-2-end)">
<row>
<xsl:for-each select="cell">
<xsl:if test="position() = 1 or
position() = 3">
<cell>
<xsl:value-of select="."/>
</cell>
</xsl:if>
</xsl:for-each>
</row>
</xsl:if>
</xsl:for-each>
</marco>
</xsl:template>
</xsl:stylesheet>
这是一个可能的解决方案(可能不是很优雅):
基本上,您可以使用XPath
position()
函数来选择所需的行
和单元格
元素的范围
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="iso-8859-1" indent="yes" omit-xml-declaration="no"/>
<xsl:template match="file">
<xsl:copy>
<xsl:apply-templates select="row[(position()>=3 and position()<=5) or (position()>=7 and position()<=8)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="row">
<xsl:copy>
<xsl:apply-templates select="cell[position()=1 or position()=3]" />
</xsl:copy>
</xsl:template>
<xsl:template match="cell">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
要在输出中选择所需的行,我想首先用一个用作过滤器的属性标记它们。
在调用XSLT的代码中,您可以在加载XML文档之后和应用转换之前使用DOM方法来完成。例如,保留吉姆·史密斯,但放弃罗伊·罗杰斯:
<row keep="-1">
<cell>Jim</cell>
<cell>Smith</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>Rogers</cell>
<cell>22</cell>
</row>
吉姆
史密斯
34
罗伊
罗杰斯
22
并将XSLT中的行更改为:
<xsl:apply-templates select="row[@keep=-1]" />
这可能是最简单、最短的解决方案,也基于使用和覆盖标识规则:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:params>
<row-range start="3" end="5"/>
<row-range start="7" end="8"/>
<cell-positions>
<pos>1</pos>
<pos>3</pos>
</cell-positions>
</my:params>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"row[(not(position() >= document('')/*/my:params/row-range[1]/@start)
or
position() > document('')/*/my:params/row-range[1]/@end
)
and
(not(position() >= document('')/*/my:params/row-range[2]/@start)
or
position() > document('')/*/my:params/row-range[2]/@end
)
]
"/>
<xsl:template match=
"cell[not(position()=document('')/*/my:params/cell-positions/*)]"/>
</xsl:stylesheet>
1.
3.
在提供的XML文档上应用此转换时:
<file>
<row>
<cell></cell>
<cell>(info...)</cell>
<cell></cell>
</row>
<row>
<cell>first name</cell>
<cell>last name</cell>
<cell>age</cell>
</row>
<row>
<cell>Jim</cell>
<cell>Smith</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>Rogers</cell>
<cell>22</cell>
</row>
<row>
<cell>Hank</cell>
<cell>Grandier</cell>
<cell>23</cell>
</row>
<row>
<cell>(info...)</cell>
<cell></cell>
<cell>(info...)</cell>
</row>
<row>
<cell>Sally</cell>
<cell>Cloud</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>Randall</cell>
<cell>44</cell>
</row>
</file>
<file>
<row>
<cell>Jim</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>22</cell>
</row>
<row>
<cell>Hank</cell>
<cell>23</cell>
</row>
<row>
<cell>Sally</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>44</cell>
</row>
</file>
(信息…)
名字
姓
年龄
吉姆
史密斯
34
罗伊
罗杰斯
22
汉克
格朗迪耶
23
(信息…)
(信息…)
俏皮话
云彩
26
约翰
兰德尔
44
生成所需的正确结果:
<file>
<row>
<cell></cell>
<cell>(info...)</cell>
<cell></cell>
</row>
<row>
<cell>first name</cell>
<cell>last name</cell>
<cell>age</cell>
</row>
<row>
<cell>Jim</cell>
<cell>Smith</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>Rogers</cell>
<cell>22</cell>
</row>
<row>
<cell>Hank</cell>
<cell>Grandier</cell>
<cell>23</cell>
</row>
<row>
<cell>(info...)</cell>
<cell></cell>
<cell>(info...)</cell>
</row>
<row>
<cell>Sally</cell>
<cell>Cloud</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>Randall</cell>
<cell>44</cell>
</row>
</file>
<file>
<row>
<cell>Jim</cell>
<cell>34</cell>
</row>
<row>
<cell>Roy</cell>
<cell>22</cell>
</row>
<row>
<cell>Hank</cell>
<cell>23</cell>
</row>
<row>
<cell>Sally</cell>
<cell>26</cell>
</row>
<row>
<cell>John</cell>
<cell>44</cell>
</row>
</file>
吉姆
34
罗伊
22
汉克
23
俏皮话
26
约翰
44
+1:如果您没有更好的标准来选择行/列(例如,单元格上的有用属性或差异化元素名称),那就是您必须要做的。这很好,有没有办法将3,5,7,8放入“映射xml”中或者其他一些数据存储并用XSLT读取?@Edward Tanguay:您可以使用
,然后从调用XSLT转换的代码中注入参数值。这类代码可以在任何需要的地方采用参数值形式:mapping.xml、DB、GUI等。要在XPath表达式中使用参数,请记住在其名称前面加上$
符号,例如(position()=$param-name-1
@MarcoS:不需要在属性值中重新输入
字符。内容模板中的位置测试仅在上下文列表位置很重要(推送样式、排序)时有用,否则在选择XPath表达式时使用它更简单。最后:“Brick”模板是awful@Alejandro:about
编码:你是对的:我编辑了上面的XSL。about“内容模板内的位置测试”:你也是对的。我写道这不是很优雅,但这是我想出的最快的解决方案。而且,在这种情况下,我不确定如何使用位置()
在一个正在选择的XPath表达式中。你能给我一个提示吗?好问题,+1。有关使用最基本的XSLT设计模式之一(覆盖标识规则)的完整、简短而简单的解决方案,请参阅我的答案。:+1好答案。在内容模板内进行验证时,可以使用常规文档(“”)/*/my:params/行范围[$vPosition>=@start和@end>=$vPosition]