Xml XSLT在转换时查找重复值
我有以下XML:Xml XSLT在转换时查找重复值,xml,xslt,xslt-1.0,grouping,Xml,Xslt,Xslt 1.0,Grouping,我有以下XML: <?xml version="1.0" encoding="utf-8"?> <NewDataSet> <GUID> <Active>true</Active> <ContractName>Contract Name</ContractName> <ContractNumber>Auto</ContractNumber&g
<?xml version="1.0" encoding="utf-8"?>
<NewDataSet>
<GUID>
<Active>true</Active>
<ContractName>Contract Name</ContractName>
<ContractNumber>Auto</ContractNumber>
<DateOfBirth>16/01/1988</DateOfBirth>
<FirstName>Fred</FirstName>
<Notes>some notes</Notes>
<PlaceOfResidence>United Kingdom</PlaceOfResidence>
<RowNumber>1</RowNumber>
<TableName>PersonDetails</TableName>
</GUID>
<GUID>
<Active>true</Active>
<ContractName>Contract Name</ContractName>
<ContractNumber>Auto</ContractNumber>
<DateOfBirth>01/01/1960</DateOfBirth>
<FirstName>Harold</FirstName>
<Notes>some notes</Notes>
<PlaceOfResidence>United Kingdom</PlaceOfResidence>
<RowNumber>2</RowNumber>
<TableName>PersonDetails</TableName>
</GUID>
<GUID>
<Active>true</Active>
<ContractName>Contract Name</ContractName>
<ContractNumber>Auto</ContractNumber>
<DateOfBirth>05/05/1955</DateOfBirth>
<FirstName>Mary</FirstName>
<Notes>some notes</Notes>
<PlaceOfResidence>United States</PlaceOfResidence>
<RowNumber>3</RowNumber>
<TableName>PersonDetails</TableName>
</GUID>
<GUID>
<ContractName>Contract Name</ContractName>
<ContractNumber>Auto</ContractNumber>
<CoverType>Property</CoverType>
<DateAdded>01/06/2017</DateAdded>
<Notes>some notes</Notes>
<RowNumber>1</RowNumber>
<TableName>Covers</TableName>
</GUID>
<GUID>
<ContractName>Contract Name</ContractName>
<ContractNumber>Auto</ContractNumber>
<CoverType>Motor</CoverType>
<DateAdded>01/06/2017</DateAdded>
<Notes>some notes</Notes>
<RowNumber>2</RowNumber>
<TableName>Covers</TableName>
</GUID>
<GUID>
<ContractName>Contract Name</ContractName>
<ContractNumber>Auto</ContractNumber>
<CoverType>Liability</CoverType>
<DateAdded>01/06/2017</DateAdded>
<Notes>some notes</Notes>
<RowNumber>3</RowNumber>
<TableName>Covers</TableName>
</GUID>
</NewDataSet>
真的
合同名称
自动的
16/01/1988
弗莱德
一些注释
大不列颠联合王国
1.
个人信息
真的
合同名称
自动的
01/01/1960
哈罗德
一些注释
大不列颠联合王国
2.
个人信息
真的
合同名称
自动的
05/05/1955
玛丽
一些注释
美国
3.
个人信息
合同名称
自动的
财产
01/06/2017
一些注释
1.
盖子
合同名称
自动的
发动机
01/06/2017
一些注释
2.
盖子
合同名称
自动的
责任
01/06/2017
一些注释
3.
盖子
我需要将其转换为以下内容:
<data>
<ContractName>Contract Name</ContractName>
<ContractNumber>Auto</ContractNumber>
<Table>
<TableRow RowNumber="1" TableName="PersonDetails">
<FirstName>Fred</FirstName>
<PlaceOfResidence>United Kingdom</PlaceOfResidence>
<DateOfBirth>16/01/1988</DateOfBirth>
<Active>true</Active>
</TableRow>
<TableRow RowNumber="2" TableName="PersonDetails">
<FirstName>Harold</FirstName>
<PlaceOfResidence>United Kingdom</PlaceOfResidence>
<DateOfBirth>01/01/1960</DateOfBirth>
<Active>true</Active>
</TableRow>
<TableRow RowNumber="3" TableName="PersonDetails">
<FirstName>Mary</FirstName>
<PlaceOfResidence>United States</PlaceOfResidence>
<DateOfBirth>05/05/1955</DateOfBirth>
<Active>true</Active>
</TableRow>
</Table>
<Table>
<TableRow RowNumber="1" TableName="Covers">
<CoverType>Property</CoverType>
<DateAdded>01/06/2017</DateAdded>
</TableRow>
<TableRow RowNumber="2" TableName="Covers">
<CoverType>Motor</CoverType>
<DateAdded>01/06/2017</DateAdded>
</TableRow>
<TableRow RowNumber="3" TableName="Covers">
<CoverType>Liability</CoverType>
<DateAdded>01/06/2017</DateAdded>
</TableRow>
</Table>
<Notes>some notes</Notes>
</data>
合同名称
自动的
弗莱德
大不列颠联合王国
16/01/1988
真的
哈罗德
大不列颠联合王国
01/01/1960
真的
玛丽
美国
05/05/1955
真的
财产
01/06/2017
发动机
01/06/2017
责任
01/06/2017
一些注释
我只能使用XSLT1.0
到目前为止,我已经:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-16"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[(*)]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/">
<data>
<xsl:apply-templates select="@* | node()"/>
</data>
</xsl:template>
</xsl:stylesheet>
它将剥离
和
标记并替换为
但是,我不确定如何生成2个表分组,以及如何自动*标识重复值:ContractName、ContractNumber和Notes
*以后可能会出现其他重复值
任何帮助或指点都将不胜感激 这里的部分挑战是您有一个
GUID
元素的平面列表,您需要根据TableName
值对这些元素进行分组。这似乎是一个非常经典的Muenchian分组方法,Jenny Tennison的网站上详细描述了这一技术:
下面是一些XSL代码,它们生成的输出几乎与所需的XML格式相同——唯一的区别在于
中元素的顺序。然而,这种转变有许多不明确的方面。我已经在代码注释中指出了这些问题
这个$kids
变量是我们确定所有GUID
结构共用的GUID
子项的关键部分。在XSL 1.0中可能有一种更优雅、更高效的方法来实现这一点;在OxygenXML(使用Saxon HE 9.6.0.7处理器)中,对小型数据集运行此操作需要0.8秒
更新了$nocopy
,以包含$kids
标识的元素名称
<!-- Begin at the beginning: the root and topmost element. -->
<xsl:template match="/NewDataSet">
<data>
<!-- We'll put common elements at the top of the `data` structure. -->
<xsl:copy-of select="$kids"/>
<!-- We want to process `GUID`s after grouping by `TableName` values.
This `for-each` is part of the Muenchian grouping technique. See
Jenny Tennison's page (linked above) for a detailed explanation. -->
<xsl:for-each select="GUID[count(. | key('table', TableName)[1]) = 1]">
<!-- If you wanted to sort alphabetically by TableName, you'd use:
<xsl:sort select="TableName" /> -->
<Table>
<!-- Now, within each `table`, we want to process all those
`GUID`s with this same corresponding `TableName`. -->
<xsl:for-each select="key('table', TableName)">
<!-- We select "this", since we want to process the matching
`GUID`, not just it's children. -->
<xsl:apply-templates select="."/>
</xsl:for-each>
</Table>
</xsl:for-each>
</data>
</xsl:template>
<!-- List up the elements we don't want to copy verbatim into each table row -->
<xsl:variable name="nocopy">
<item>RowNumber</item>
<item>TableName</item>
<!-- Copy in the bits from $kids -->
<xsl:for-each select="$kids/*">
<item><xsl:value-of select="name(.)"/></item>
</xsl:for-each>
</xsl:variable>
<xsl:template match="GUID">
<TableRow RowNumber="{RowNumber}" TableName="{TableName}">
<!-- Copy over child data, but _only_ if it's not in `$nocopy` -->
<xsl:copy-of select="*[not(name() = $nocopy/item)]"/>
</TableRow>
</xsl:template>
行数
表名
现在,这将生成与所需输出XML功能相同的输出。唯一的区别是元素的顺序——TableRow
子元素的顺序不同,Notes
位于data
的顶部,与ContractName
和ContractNumber
并列,而不是位于data
的底部
关于输出XML数据格式的说明
将表名作为属性包含在每个表行中似乎有点奇怪。将其作为表
元素本身的一个属性会更有意义
类似地,在每一行上都有RowNumber
属性似乎是多余的。只需查看父级表中每个表行的位置()
,即可收集此信息
也就是说,您知道自己的需求。那么,这只是让事情正常运转的问题。:) 这里的部分挑战是您有一个GUID
元素的平面列表,您需要根据TableName
值对这些元素进行分组。这似乎是一个非常经典的Muenchian分组方法,Jenny Tennison的网站上详细描述了这一技术:
下面是一些XSL代码,它们生成的输出几乎与所需的XML格式相同——唯一的区别在于
中元素的顺序。然而,这种转变有许多不明确的方面。我已经在代码注释中指出了这些问题
这个$kids
变量是我们确定所有GUID
结构共用的GUID
子项的关键部分。在XSL 1.0中可能有一种更优雅、更高效的方法来实现这一点;在OxygenXML(使用Saxon HE 9.6.0.7处理器)中,对小型数据集运行此操作需要0.8秒
更新了$nocopy
,以包含$kids
标识的元素名称
<!-- Begin at the beginning: the root and topmost element. -->
<xsl:template match="/NewDataSet">
<data>
<!-- We'll put common elements at the top of the `data` structure. -->
<xsl:copy-of select="$kids"/>
<!-- We want to process `GUID`s after grouping by `TableName` values.
This `for-each` is part of the Muenchian grouping technique. See
Jenny Tennison's page (linked above) for a detailed explanation. -->
<xsl:for-each select="GUID[count(. | key('table', TableName)[1]) = 1]">
<!-- If you wanted to sort alphabetically by TableName, you'd use:
<xsl:sort select="TableName" /> -->
<Table>
<!-- Now, within each `table`, we want to process all those
`GUID`s with this same corresponding `TableName`. -->
<xsl:for-each select="key('table', TableName)">
<!-- We select "this", since we want to process the matching
`GUID`, not just it's children. -->
<xsl:apply-templates select="."/>
</xsl:for-each>
</Table>
</xsl:for-each>
</data>
</xsl:template>
<!-- List up the elements we don't want to copy verbatim into each table row -->
<xsl:variable name="nocopy">
<item>RowNumber</item>
<item>TableName</item>
<!-- Copy in the bits from $kids -->
<xsl:for-each select="$kids/*">
<item><xsl:value-of select="name(.)"/></item>
</xsl:for-each>
</xsl:variable>
<xsl:template match="GUID">
<TableRow RowNumber="{RowNumber}" TableName="{TableName}">
<!-- Copy over child data, but _only_ if it's not in `$nocopy` -->
<xsl:copy-of select="*[not(name() = $nocopy/item)]"/>
</TableRow>
</xsl:template>
行数
表名
现在,这将生成与所需输出XML功能相同的输出。唯一的区别是元素的顺序——TableRow
子元素的顺序不同,Notes
位于data
的顶部,与ContractName
和ContractNumber
并列,而不是位于data
的底部
关于输出XML数据格式的说明
将表名作为属性包含在每个表行中似乎有点奇怪。将其作为表
元素本身的一个属性会更有意义
类似地,在每一行上都有RowNumber
属性似乎是多余的。这些信息可以通过查看
<!-- List up the elements we don't want to copy verbatim into each table row -->
<xsl:variable name="nocopy">
<item>RowNumber</item>
<item>TableName</item>
<!-- Copy in the bits from $kids -->
<xsl:for-each select="$kids/*">
<item><xsl:value-of select="name(.)"/></item>
</xsl:for-each>
</xsl:variable>
<xsl:template match="GUID">
<TableRow RowNumber="{RowNumber}" TableName="{TableName}">
<!-- Copy over child data, but _only_ if it's not in `$nocopy` -->
<xsl:copy-of select="*[not(name() = $nocopy/item)]"/>
</TableRow>
</xsl:template>