分组时无法复制不匹配的节点
Unable to Copy unmatched Nodes while Grouping
我无法找出我应该做什么才能获得如下所示的所需输出。
有人可以帮帮我吗?谢谢!
来源XML
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<empID>12345</empID>
<Location>NY</Location>
<Remote/>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
<Local/>
<Location>NY</Location>
<City>NYC</City>
<CityAllowance>100</CityAllowance>
<Remote>Y</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
<Local>Y</Local>
<Location>NY</Location>
<City>Syracuse</City>
<CityAllowance>150</CityAllowance>
<Remote>Y</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
<Local>Y</Local>
<Location>NY</Location>
<City>Ithaca</City>
<CityAllowance>250</CityAllowance>
<Remote>Y</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>88001</empID>
<Local/>
<Location>CA</Location>
<City>San Franscisco</City>
<CityAllowance>200</CityAllowance>
<Remote>N</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>88001</empID>
<Local>Y</Local>
<Location>CA</Location>
<City>San Jose</City>
<CityAllowance>190</CityAllowance>
<Remote>N</Remote>
<Amount>9450</Amount>
</Worker>
<Worker>
<empID>88001</empID>
<Local>Y</Local>
<Location>CA</Location>
<City>Oakland</City>
<CityAllowance>600</CityAllowance>
<Remote>N</Remote>
<Amount>4500</Amount>
</Worker>
</Workers>
我的 XSLT 是
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Workers">
<Workers>
<xsl:for-each-group select="Worker[Remote = 'Y' or Remote = 'N']" group-by="empID">
<Worker>
<empID>
<xsl:value-of select="current-grouping-key()"/>
</empID>
</Worker>
</xsl:for-each-group>
</Workers>
</xsl:template>
</xsl:stylesheet>
预期输出
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<empID>12345</empID>
<Location>NY</Location>
<Remote/>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
</Worker>
<Worker>
<empID>88001</empID>
</Worker>
</Workers>
当前输出
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<empID>23456</empID>
</Worker>
<Worker>
<empID>88001</empID>
</Worker>
</Workers>
如果
<Local>
的值是 Y
或 N
。然而,这并没有被我当前的 XSLT
复制下来
For-each-group 语句 <xsl:for-each-group select="Worker[Remote = 'Y' or Remote = 'N']" group-by="empID">
用于处理 <Local>
值设置为 Y
或 N
[ 的记录=23=]
我的应用程序同时支持 XSLT 3.0
和 XSLT 2.0
一种方法是使用键并为您不想输出的元素添加空模板:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="group" match="Worker[Remote = 'Y' or Remote = 'N']" use="empID"/>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N'][not(. is key('group', empID)[1])]"/>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N'][. is key('group', empID)[1]]/*[not(self::empID)]"/>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>
如果您想对一些元素进行分组,但要使用 for-each-group
处理所有元素,一种方法是使用变量:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Workers">
<xsl:copy>
<xsl:variable name="groups" as="element(Worker)*">
<xsl:for-each-group select="Worker" composite="yes" group-by="Remote = 'Y' or Remote = 'N', empID">
<xsl:choose>
<xsl:when test="current-grouping-key()[1]">
<xsl:sequence select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$groups/."/>
</xsl:copy>
</xsl:template>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N']/*[not(self::empID)]"/>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>
也许最好将分组代码移动到一个函数中,这样 Workers
的模板主体仍然紧凑:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns:mf="http://example.com/mf"
expand-text="yes">
<xsl:function name="mf:group" as="element(Worker)*">
<xsl:param name="workers" as="element(Worker)*"/>
<xsl:for-each-group select="$workers" composite="yes" group-by="Remote = 'Y' or Remote = 'N', empID">
<xsl:choose>
<xsl:when test="current-grouping-key()[1]">
<xsl:sequence select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Workers">
<xsl:copy>
<xsl:apply-templates select="mf:group(Worker)/."/>
</xsl:copy>
</xsl:template>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N']/*[not(self::empID)]"/>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>
我无法找出我应该做什么才能获得如下所示的所需输出。
有人可以帮帮我吗?谢谢!
来源XML
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<empID>12345</empID>
<Location>NY</Location>
<Remote/>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
<Local/>
<Location>NY</Location>
<City>NYC</City>
<CityAllowance>100</CityAllowance>
<Remote>Y</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
<Local>Y</Local>
<Location>NY</Location>
<City>Syracuse</City>
<CityAllowance>150</CityAllowance>
<Remote>Y</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
<Local>Y</Local>
<Location>NY</Location>
<City>Ithaca</City>
<CityAllowance>250</CityAllowance>
<Remote>Y</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>88001</empID>
<Local/>
<Location>CA</Location>
<City>San Franscisco</City>
<CityAllowance>200</CityAllowance>
<Remote>N</Remote>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>88001</empID>
<Local>Y</Local>
<Location>CA</Location>
<City>San Jose</City>
<CityAllowance>190</CityAllowance>
<Remote>N</Remote>
<Amount>9450</Amount>
</Worker>
<Worker>
<empID>88001</empID>
<Local>Y</Local>
<Location>CA</Location>
<City>Oakland</City>
<CityAllowance>600</CityAllowance>
<Remote>N</Remote>
<Amount>4500</Amount>
</Worker>
</Workers>
我的 XSLT 是
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Workers">
<Workers>
<xsl:for-each-group select="Worker[Remote = 'Y' or Remote = 'N']" group-by="empID">
<Worker>
<empID>
<xsl:value-of select="current-grouping-key()"/>
</empID>
</Worker>
</xsl:for-each-group>
</Workers>
</xsl:template>
</xsl:stylesheet>
预期输出
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<empID>12345</empID>
<Location>NY</Location>
<Remote/>
<Amount>1450</Amount>
</Worker>
<Worker>
<empID>23456</empID>
</Worker>
<Worker>
<empID>88001</empID>
</Worker>
</Workers>
当前输出
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<empID>23456</empID>
</Worker>
<Worker>
<empID>88001</empID>
</Worker>
</Workers>
如果
复制下来<Local>
的值是Y
或N
。然而,这并没有被我当前的 XSLTFor-each-group 语句
<xsl:for-each-group select="Worker[Remote = 'Y' or Remote = 'N']" group-by="empID">
用于处理<Local>
值设置为Y
或N
[ 的记录=23=]
我的应用程序同时支持 XSLT 3.0
和 XSLT 2.0
一种方法是使用键并为您不想输出的元素添加空模板:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="group" match="Worker[Remote = 'Y' or Remote = 'N']" use="empID"/>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N'][not(. is key('group', empID)[1])]"/>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N'][. is key('group', empID)[1]]/*[not(self::empID)]"/>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>
如果您想对一些元素进行分组,但要使用 for-each-group
处理所有元素,一种方法是使用变量:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Workers">
<xsl:copy>
<xsl:variable name="groups" as="element(Worker)*">
<xsl:for-each-group select="Worker" composite="yes" group-by="Remote = 'Y' or Remote = 'N', empID">
<xsl:choose>
<xsl:when test="current-grouping-key()[1]">
<xsl:sequence select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$groups/."/>
</xsl:copy>
</xsl:template>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N']/*[not(self::empID)]"/>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>
也许最好将分组代码移动到一个函数中,这样 Workers
的模板主体仍然紧凑:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns:mf="http://example.com/mf"
expand-text="yes">
<xsl:function name="mf:group" as="element(Worker)*">
<xsl:param name="workers" as="element(Worker)*"/>
<xsl:for-each-group select="$workers" composite="yes" group-by="Remote = 'Y' or Remote = 'N', empID">
<xsl:choose>
<xsl:when test="current-grouping-key()[1]">
<xsl:sequence select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Workers">
<xsl:copy>
<xsl:apply-templates select="mf:group(Worker)/."/>
</xsl:copy>
</xsl:template>
<xsl:template match="Worker[Remote = 'Y' or Remote = 'N']/*[not(self::empID)]"/>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>