XSLT1 转换
XSLT1 Transformation
我需要转换这个输入 XML:
<Log1>
<Connection User="Peter" Host="Computer01" Port="22"/>
<Connection User="Peter" Host="Computer02" Port="22"/>
<Connection User="Peter" Host="Computer02" Port="80"/>
<Connection User="David" Host="Computer01" Port="8080"/>
<Connection User="David" Host="Computer01" Port="8080"/>
<Connection User="David" Host="Computer01" Port="8080"/>
<Connection User="David" Host="Computer03" Port="22"/>
<Connection User="David" Host="Computer04" Port="21"/>
</Log1>
进入那个输出 XML:
<Log2>
<Event Name="David" Target="Computer01|Computer03|Computer04"/>
<Event Name="Peter" Target="Computer01|Computer02"/>
</Log2>
到目前为止,我使用了 Muenchian 分组并获得了类似的东西:
<Log2>
<Event Name="David" Target="Computer01|Computer01|Computer01|Computer03|Computer04"/>
<Event Name="Peter" Target="Computer01|Computer02|computer02"/>
</Log2>
问题是我无法去除输出中的重复机器。
这是我的 XSLT:
<xsl:key name="myKey" match="Connection" use="@User"/>
<xsl:variable name="separator" select="'|'"/>
<xsl:template match="Log1">
<xsl:element name="Log2">
<xsl:for-each select="Connection[count(. | key('myKey', @User)[1]) = 1]">
<xsl:sort select="@User" />
<xsl:element name="Event">
<xsl:attribute name="Name">
<xsl:value-of select="@User" />
</xsl:attribute>
<xsl:attribute name="Target">
<xsl:for-each select="key('myKey', @User)">
<xsl:sort select="@Host" />
<xsl:value-of select="@Host" />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
你们能帮我使用 XSLT 1.0 处理器吗?
您实际上需要在此处进行第二组 Muenchian 分组,因为您还需要对 "User" 和 "Host" 的组合进行分组以获得不同的 Host
属性每个用户。所以,你需要像这样的第二把钥匙:
<xsl:key name="myKey2" match="Connection" use="concat(@User, '|', @Host)"/>
(注意竖线 |
可以是任何东西,只要它不出现在 User
或 Host
中即可)。
然后你在你的内心 xsl:for-each
中像这样使用:
<xsl:for-each select="key('myKey', @User)[count(. | key('myKey2', concat(@User, '|', @Host))[1]) = 1]">
试试这个 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="myKey" match="Connection" use="@User"/>
<xsl:key name="myKey2" match="Connection" use="concat(@User, '|', @Host)"/>
<xsl:variable name="separator" select="'|'"/>
<xsl:template match="Log1">
<xsl:element name="Log2">
<xsl:for-each select="Connection[count(. | key('myKey', @User)[1]) = 1]">
<xsl:sort select="@User" />
<xsl:element name="Event">
<xsl:attribute name="Name">
<xsl:value-of select="@User" />
</xsl:attribute>
<xsl:attribute name="Target">
<xsl:for-each select="key('myKey', @User)[count(. | key('myKey2', concat(@User, '|', @Host))[1]) = 1]">
<xsl:sort select="@Host" />
<xsl:value-of select="@Host" />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
附带说明一下,没有真正需要使用xsl:element
来创建具有静态名称的元素,直接将元素写出来即可。例如
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="myKey" match="Connection" use="@User"/>
<xsl:key name="myKey2" match="Connection" use="concat(@User, '|', @Host)"/>
<xsl:variable name="separator" select="'|'"/>
<xsl:template match="Log1">
<Log2>
<xsl:for-each select="Connection[count(. | key('myKey', @User)[1]) = 1]">
<xsl:sort select="@User" />
<Event Name="{@User}">
<xsl:attribute name="Target">
<xsl:for-each select="key('myKey', @User)[count(. | key('myKey2', concat(@User, '|', @Host))[1]) = 1]">
<xsl:sort select="@Host" />
<xsl:value-of select="@Host" />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</Event>
</xsl:for-each>
</Log2>
</xsl:template>
</xsl:stylesheet>
另请注意在创建 Name
属性时使用属性值模板。
我需要转换这个输入 XML:
<Log1>
<Connection User="Peter" Host="Computer01" Port="22"/>
<Connection User="Peter" Host="Computer02" Port="22"/>
<Connection User="Peter" Host="Computer02" Port="80"/>
<Connection User="David" Host="Computer01" Port="8080"/>
<Connection User="David" Host="Computer01" Port="8080"/>
<Connection User="David" Host="Computer01" Port="8080"/>
<Connection User="David" Host="Computer03" Port="22"/>
<Connection User="David" Host="Computer04" Port="21"/>
</Log1>
进入那个输出 XML:
<Log2>
<Event Name="David" Target="Computer01|Computer03|Computer04"/>
<Event Name="Peter" Target="Computer01|Computer02"/>
</Log2>
到目前为止,我使用了 Muenchian 分组并获得了类似的东西:
<Log2>
<Event Name="David" Target="Computer01|Computer01|Computer01|Computer03|Computer04"/>
<Event Name="Peter" Target="Computer01|Computer02|computer02"/>
</Log2>
问题是我无法去除输出中的重复机器。
这是我的 XSLT:
<xsl:key name="myKey" match="Connection" use="@User"/>
<xsl:variable name="separator" select="'|'"/>
<xsl:template match="Log1">
<xsl:element name="Log2">
<xsl:for-each select="Connection[count(. | key('myKey', @User)[1]) = 1]">
<xsl:sort select="@User" />
<xsl:element name="Event">
<xsl:attribute name="Name">
<xsl:value-of select="@User" />
</xsl:attribute>
<xsl:attribute name="Target">
<xsl:for-each select="key('myKey', @User)">
<xsl:sort select="@Host" />
<xsl:value-of select="@Host" />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
你们能帮我使用 XSLT 1.0 处理器吗?
您实际上需要在此处进行第二组 Muenchian 分组,因为您还需要对 "User" 和 "Host" 的组合进行分组以获得不同的 Host
属性每个用户。所以,你需要像这样的第二把钥匙:
<xsl:key name="myKey2" match="Connection" use="concat(@User, '|', @Host)"/>
(注意竖线 |
可以是任何东西,只要它不出现在 User
或 Host
中即可)。
然后你在你的内心 xsl:for-each
中像这样使用:
<xsl:for-each select="key('myKey', @User)[count(. | key('myKey2', concat(@User, '|', @Host))[1]) = 1]">
试试这个 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="myKey" match="Connection" use="@User"/>
<xsl:key name="myKey2" match="Connection" use="concat(@User, '|', @Host)"/>
<xsl:variable name="separator" select="'|'"/>
<xsl:template match="Log1">
<xsl:element name="Log2">
<xsl:for-each select="Connection[count(. | key('myKey', @User)[1]) = 1]">
<xsl:sort select="@User" />
<xsl:element name="Event">
<xsl:attribute name="Name">
<xsl:value-of select="@User" />
</xsl:attribute>
<xsl:attribute name="Target">
<xsl:for-each select="key('myKey', @User)[count(. | key('myKey2', concat(@User, '|', @Host))[1]) = 1]">
<xsl:sort select="@Host" />
<xsl:value-of select="@Host" />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
附带说明一下,没有真正需要使用xsl:element
来创建具有静态名称的元素,直接将元素写出来即可。例如
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="myKey" match="Connection" use="@User"/>
<xsl:key name="myKey2" match="Connection" use="concat(@User, '|', @Host)"/>
<xsl:variable name="separator" select="'|'"/>
<xsl:template match="Log1">
<Log2>
<xsl:for-each select="Connection[count(. | key('myKey', @User)[1]) = 1]">
<xsl:sort select="@User" />
<Event Name="{@User}">
<xsl:attribute name="Target">
<xsl:for-each select="key('myKey', @User)[count(. | key('myKey2', concat(@User, '|', @Host))[1]) = 1]">
<xsl:sort select="@Host" />
<xsl:value-of select="@Host" />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</Event>
</xsl:for-each>
</Log2>
</xsl:template>
</xsl:stylesheet>
另请注意在创建 Name
属性时使用属性值模板。