问题描述
|
我有一些看起来像这样的XML
<Data>
<MainItem>
<ItemGroup>Foo</ItemGroup>
<ItemDetails>Details</ItemDetails>
</MainItem>
<MainItem>
<ItemGroup>Bar</ItemGroup>
<ItemDetails>Details</ItemDetails>
</MainItem>
<MainItem>
<ItemGroup>Baz</ItemGroup>
<ItemDetails>Details</ItemDetails>
</MainItem>
<OtherData>
<ItemGroup>Foo</ItemGroup>
<OtherDataDetails>Blah</OtherDataDetails>
</OtherData>
<OtherData>
<ItemGroup>Bar</ItemGroup>
<OtherDataDetails>BlahBlah</OtherDataDetails>
</OtherData>
<OtherData>
<ItemGroup>Baz</ItemGroup>
<OtherDataDetails>BlahBlahBlahBlahBlah</OtherDataDetails>
</OtherData>
</Data>
我正在尝试进行的转换与此类似:
Foo
- Details
- Blah
Bar
- Details
- BlahBlah
Baz
- Details
- BlahBlahBlahBlahBlah
使用XSLT 1.0。
我目前正在通过类似于Muenchian方法的方法来完成分组。但是我不确定如何将标签中的数据导入到我的分组中。有小费吗?
解决方法
尝试这样的事情:
<?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\" />
<xsl:key name=\"groups\" match=\"//ItemGroup\" use=\"text()\" />
<xsl:template match=\"/\">
<Data>
<xsl:apply-templates
select=\"//ItemGroup[count( . | key(\'groups\',text())[1]) = 1]\" />
</Data>
</xsl:template>
<xsl:template match=\"ItemGroup\">
<xsl:variable name=\"text\" select=\"text()\" />
<Group><xsl:value-of select=\"$text\" /></Group>
<xsl:for-each select=\"/Data/*[ItemGroup = $text]/*[contains(name(),\'Details\')]\">
<Detail>- <xsl:value-of select=\".\" /></Detail>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我为您建立了一个有效的例子。
, 以下分组解决方案不使用循环,而是照顾ItemGroup
之后的任何其他同级元素。此外,仅使用基于“ 4”的小钥匙来识别组。
Saxon 6.5.5下的XSLT 1.0
产生文字:
<xsl:stylesheet version=\"1.0\"
xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">
<xsl:output omit-xml-declaration=\"yes\" method=\"xml\" indent=\"yes\"/>
<xsl:strip-space elements=\"*\"/>
<xsl:key name=\"main\" match=\"MainItem/ItemGroup\" use=\"text()\"/>
<xsl:template match=\"/Data\">
<xsl:apply-templates select=\"MainItem\"/>
</xsl:template>
<xsl:template match=\"MainItem\">
<xsl:value-of select=\"ItemGroup\"/><xsl:text>
</xsl:text>
<xsl:apply-templates select=\"ItemGroup[generate-id(.)=generate-id(key(\'main\',current()/ItemGroup)[1])]\"/>
</xsl:template>
<xsl:template match=\"ItemGroup\">
<xsl:apply-templates select=\"/Data/*[ItemGroup = current()]/*/following-sibling::*\"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match=\"*\">
<xsl:text>- </xsl:text><xsl:value-of select=\".\"/><xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
应用于您的输入,将产生:
Foo
- Details
- Blah
Bar
- Details
- BlahBlah
Baz
- Details
- BlahBlahBlahBlahBlah
产生XML输出:
<xsl:stylesheet version=\"1.0\"
xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">
<xsl:output omit-xml-declaration=\"yes\" method=\"xml\" indent=\"yes\"/>
<xsl:strip-space elements=\"*\"/>
<xsl:key name=\"main\" match=\"MainItem/ItemGroup\" use=\"text()\"/>
<xsl:template match=\"/Data\">
<xsl:copy>
<xsl:apply-templates select=\"MainItem\"/>
</xsl:copy>
</xsl:template>
<xsl:template match=\"MainItem\">
<xsl:variable name=\"id\" select=\"ItemGroup\"/>
<Group id=\"{$id}\">
<xsl:apply-templates select=\"ItemGroup[generate-id(.)=generate-id(key(\'main\',current()/ItemGroup)[1])]\"/>
</Group>
</xsl:template>
<xsl:template match=\"ItemGroup\">
<xsl:copy-of select=\"/Data/*[ItemGroup = current()]/*/following-sibling::*\"/>
</xsl:template>
</xsl:stylesheet>
产生:
<Data>
<Group id=\"Foo\">
<ItemDetails>Details</ItemDetails>
<OtherDataDetails>Blah</OtherDataDetails>
</Group>
<Group id=\"Bar\">
<ItemDetails>Details</ItemDetails>
<OtherDataDetails>BlahBlah</OtherDataDetails>
</Group>
<Group id=\"Baz\">
<ItemDetails>Details</ItemDetails>
<OtherDataDetails>BlahBlahBlahBlahBlah</OtherDataDetails>
</Group>
</Data>
, 这是仅使用模板和键的非常简短且最有效的转换:
<xsl:stylesheet version=\"1.0\"
xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">
<xsl:output method=\"text\"/>
<xsl:key name=\"kGroupByVal\" match=\"ItemGroup\"
use=\".\"/>
<xsl:key name=\"kNonGroupByGroup\"
match=\"*[not(self::ItemGroup)]\" use=\"../ItemGroup\"/>
<xsl:template match=
\"ItemGroup[generate-id()
=
generate-id(key(\'kGroupByVal\',.)[1])
]
\">
<xsl:value-of select=\"concat(\'
\',.)\"/>
<xsl:apply-templates mode=\"listGroup\"
select=\"key(\'kNonGroupByGroup\',.)\"/>
</xsl:template>
<xsl:template match=\"*\" mode=\"listGroup\">
<xsl:value-of select=\"concat(\'
 - \',.)\"/>
</xsl:template>
<xsl:template match=\"text()\"/>
</xsl:stylesheet>
当应用于提供的XML文档时:
<Data>
<MainItem>
<ItemGroup>Foo</ItemGroup>
<ItemDetails>Details</ItemDetails>
</MainItem>
<MainItem>
<ItemGroup>Bar</ItemGroup>
<ItemDetails>Details</ItemDetails>
</MainItem>
<MainItem>
<ItemGroup>Baz</ItemGroup>
<ItemDetails>Details</ItemDetails>
</MainItem>
<OtherData>
<ItemGroup>Foo</ItemGroup>
<OtherDataDetails>Blah</OtherDataDetails>
</OtherData>
<OtherData>
<ItemGroup>Bar</ItemGroup>
<OtherDataDetails>BlahBlah</OtherDataDetails>
</OtherData>
<OtherData>
<ItemGroup>Baz</ItemGroup>
<OtherDataDetails>BlahBlahBlahBlahBlah</OtherDataDetails>
</OtherData>
</Data>
所需的正确结果产生了:
Foo
- Details
- Blah
Bar
- Details
- BlahBlah
Baz
- Details
- BlahBlahBlahBlahBlah
**说明**:
Muenchian分组得到ing3ѭ的不同值。
用于通过所有非3个元素的同级索引所有非3个元素的键。
空模板与任何文本节点匹配,以防止内置XSLT模板输出任何文本节点。