我的XML结构就像
<Client>
<Document>
<service class="ABC">
<author name="x"/>
<Details>
...
</Details>
</service>
</Document>
<Document>
<service class="ABC">
<author name="x"/>
<Details>
...
</Details>
</service>
</Document>
<Document>
<service class="ABC">
<author name="x"/>
<Details>
...
</Details>
</service>
</Document>'
</Client>
我希望它像
<Client>
<Document>
<service class="ABC">
<author name="x"/>
<Details>
...
</Details>
</service>
</Document>
<Document>
<service class="ABC">
<author name="x"/>
<Details>
...
</Details>
</service>
</Document>
<Document>
<service class="ABC">
<author name="x"/>
<Details>
...
</Details>
</service>
</Document>'
<component>
<service class="ABC">
<author name="x"/>
</service>
</component>'
</Client>
我的xsl文件包含
<xsl:template match="//v3:Client">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<component>
<service class="">
<xsl:apply-templates select="//v3:Client/v3:Document/v3:service/v3:author"/>
</service>
</component>
</xsl:copy>
</xsl:template>
<xsl:template match="//v3:Client/v3:component/v3:service">
<xsl:element name="service" namespace="urn:hl7-org:v3">
<xsl:attribute name="class">
<xsl:value-of select="//v3:Client/v3:Document/v3:service/@class"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
但它没有给出理想的输出。它的输出类似于
Client Document service class="ABC" author name="x" details ... details service Document Document service class="ABC" author name="x" details ... details service Document Document service class="ABC" author name="x" details ... details service Document component service class="" author name="x" service service class="" author name="x" service service class="" author name="x" service component Client
我是xsl的新手。有人可以帮我解决这个问题吗?
答案 0 :(得分:0)
使用group-by
功能:
<?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" />
<xsl:template match="/Client">
<xsl:copy-of select="Document" />
<!-- Group nodes by attribute value, produce one <component>
per each group -->
<xsl:for-each-group select="Document" group-by="service/@class">
<component>
<xsl:copy-of select="./service" />
</component>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
上面的样式表为每个<component>
属性值生成一个Document class=""
。
答案 1 :(得分:0)
如果您无法访问group-by
,则可以考虑使用following-sibling::
轴。
换句话说,你正在寻找这样的东西:
<component>
<xsl:apply-templates select="Document/service[@class != following-sibling::service/@class]" mode="component" />
</component>
<xsl:template match="service" mode="component">
<service class="{@class}">
<!-- etc. -->
</service>
</xsl:template>
答案 2 :(得分:0)
如果要在组件元素中输出不同的服务元素,那么在XSTL1.0中,您需要使用一种名为 Muenchian分组的技术。我假设类属性唯一标识一个服务,因此您首先要定义一个键来查找服务,如此
<xsl:key name="service" match="service" use="@class" />
然后,在创建组件元素时,要获取不同的服务元素,您需要查看所有这些元素,但只选择键中首先出现的元素对于他们的类属性。
<xsl:apply-templates
select="Document/service[generate-id() = generate-id(key('service', @class)[1])]"
mode="component" />
在与服务元素匹配的模板中,您可以根据需要输出详细信息。在您的示例中,您似乎只需要作者元素,而不是详细信息。
<xsl:template match="service" mode="component">
<xsl:copy>
<xsl:apply-templates select="author|@*"/>
</xsl:copy>
</xsl:template>
模式的使用是因为您只想在输出compenent元素时匹配此模板。
这是完整的XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="service" match="service" use="@class" />
<xsl:template match="Client">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<component>
<xsl:apply-templates select="Document/service[generate-id() = generate-id(key('service', @class)[1])]" mode="component" />
</component>
</xsl:copy>
</xsl:template>
<xsl:template match="service" mode="component">
<xsl:copy>
<xsl:apply-templates select="author|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,输出以下内容
<Client>
<Document>
<service class="ABC">
<author name="x"/>
<Details> ... </Details>
</service>
</Document>
<Document>
<service class="ABC">
<author name="x"/>
<Details> ... </Details>
</service>
</Document>
<Document>
<service class="ABC">
<author name="x"/>
<Details> ... </Details>
</service>
</Document>
<component>
<service class="ABC">
<author name="x"/>
</service>
</component>
</Client>