我有一个表模式,其中包含一些元数据,我需要将其下拉到行级别。
所以这......
<tables>
<table name="T01">
<columns>
<column name="F01">
<heading>Field 1</heading>
</column >
<column name="F02">
<heading>Field 2</heading>
</column>
</columns>
<rows>
<row>
<field name="F01">AAAAA</field>
<field name="F02">BBBBB</field>
</row>
<row>
<field name="F01">DDDDD</field>
<field name="F02">EEEEE</field>
</row>
</rows>
</table>
<table name="T02">
<!-- ... -->
</table>
</tables>
应该成为这个......
<tables>
<table name="T01">
<rows>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>AAAAA</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>BBBBB</value>
</field>
</row>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>DDDDD</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>EEEEE</value>
</field>
</row>
</rows>
</table>
<table name="T02">
<!-- ... -->
</table>
</tables>
我确信有很多简单的方法可以使用XSLT来实现这一点,但由于我的工具,我真的需要通过key()检索列标题。所以像这样......
<?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"/>
<!-- This won't work but if it did ... -->
<xsl:key name="field-heading"
match="../../columns/column/heading"
use="../@name" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="field">
<field name="{@name}">
<heading>
<xsl:value-of select="key('field-heading', @name)"/>
</heading>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:template>
<xsl:template match="columns"/>
</xsl:stylesheet>
但xsl:key match属性不允许父轴,我不确定是否还有其他方法使其适合。
答案 0 :(得分:0)
主要问题是密钥定义的上下文是文档而不是您使用密钥的位置,因此定义应该是
<xsl:key name="field-heading"
match="/tables/table/columns/column/heading"
use="../@name" />
你的XML中有一些拼写错误 - 这就是我认为它应该是
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="C:/Users/morank/Documents/temp/code.xsl"?>
<tables>
<table name="T01">
<columns>
<column name="F01">
<heading>Field 1</heading>
</column>
<column name="F02">
<heading>Field 2</heading>
</column>
</columns>
<rows>
<row>
<field name="F01">AAAAA</field>
<field name="F02">BBBBB</field>
</row>
<row>
<field name="F01">DDDDD</field>
<field name="F02">EEEEE</field>
</row>
</rows>
</table>
<table name="T02">
<!-- ... -->
</table>
</tables>
应用以下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"/>
<!-- This won't work but if it did ... -->
<xsl:key name="field-heading"
match="/tables/table/columns/column/heading"
use="../@name" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="field">
<field name='{@name}'>
<heading>
<xsl:value-of select="key('field-heading', @name)"/>
</heading>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:template>
<xsl:template match="columns"/>
</xsl:stylesheet>
提供所需的输出:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="C:/Users/morank/Documents/temp/code.xsl"?><tables>
<table name="T01">
<rows>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>AAAAA</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>BBBBB</value>
</field>
</row>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>DDDDD</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>EEEEE</value>
</field>
</row>
</rows>
</table>
<table name="T02">
<!-- ... -->
</table>
</tables>
请注意,我还将模板更改为标准身份转换,并确保已复制字段名称
答案 1 :(得分:0)
尝试使用:
<xsl:key name="field-heading"
match="heading"
use="parent::column/@name" />
在这种情况下,../
无法正常工作,因为use
路径不是从root开始的。
修改强>
尝试使用table/@name
和column/@name
创建密钥。这应该是独一无二的。
XML输入(我希望这代表您评论中的问题。)
<tables>
<table name="T01">
<columns>
<column name="F01">
<heading>Field 1</heading>
</column>
<column name="F02">
<heading>Field 2</heading>
</column>
</columns>
<rows>
<row>
<field name="F01">AAAAA</field>
<field name="F02">BBBBB</field>
</row>
<row>
<field name="F01">DDDDD</field>
<field name="F02">EEEEE</field>
</row>
</rows>
</table>
<table name="T02">
<columns>
<column name="F01">
<heading>Field A</heading>
</column>
<column name="F02">
<heading>Field B</heading>
</column>
</columns>
<rows>
<row>
<field name="F01">11111</field>
<field name="F02">22222</field>
</row>
<row>
<field name="F01">44444</field>
<field name="F02">55555</field>
</row>
</rows>
</table>
</tables>
修改后的XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- This won't work but if it did ... -->
<xsl:key name="field-heading"
match="heading"
use="concat(ancestor::table/@name,'+',parent::column/@name)" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="field">
<field name="{@name}">
<heading>
<xsl:value-of select="key('field-heading', concat(ancestor::table/@name,'+',@name))"/>
</heading>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:template>
<xsl:template match="columns"/>
</xsl:stylesheet>
XML输出
<tables>
<table name="T01">
<rows>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>AAAAA</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>BBBBB</value>
</field>
</row>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>DDDDD</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>EEEEE</value>
</field>
</row>
</rows>
</table>
<table name="T02">
<rows>
<row>
<field name="F01">
<heading>Field A</heading>
<value>11111</value>
</field>
<field name="F02">
<heading>Field B</heading>
<value>22222</value>
</field>
</row>
<row>
<field name="F01">
<heading>Field A</heading>
<value>44444</value>
</field>
<field name="F02">
<heading>Field B</heading>
<value>55555</value>
</field>
</row>
</rows>
</table>
</tables>
答案 2 :(得分:0)
稍微简单的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kColByNames" match="column" use=
"concat(../../@name, '+', @name)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="field">
<xsl:copy>
<xsl:copy-of select="@*"/>
<heading>
<xsl:value-of select=
"key('kColByNames', concat(ancestor::table[1]/@name, '+', @name))"/>
</heading>
<value><xsl:value-of select="."/></value>
</xsl:copy>
</xsl:template>
<xsl:template match="columns"/>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<tables>
<table name="T01">
<columns>
<column name="F01">
<heading>Field 1</heading>
</column>
<column name="F02">
<heading>Field 2</heading>
</column>
</columns>
<rows>
<row>
<field name="F01">AAAAA</field>
<field name="F02">BBBBB</field>
</row>
<row>
<field name="F01">DDDDD</field>
<field name="F02">EEEEE</field>
</row>
</rows>
</table>
<table name="T02">
<!-- ... -->
</table>
</tables>
产生了想要的正确结果:
<tables>
<table name="T01">
<rows>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>AAAAA</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>BBBBB</value>
</field>
</row>
<row>
<field name="F01">
<heading>Field 1</heading>
<value>DDDDD</value>
</field>
<field name="F02">
<heading>Field 2</heading>
<value>EEEEE</value>
</field>
</row>
</rows>
</table>
<table name="T02"><!-- ... --></table>
</tables>
解释:覆盖身份规则并使用复合密钥 - column
由name
属性的对标识,其祖父母name
的{{1}}属性。