我有两个XML文件,它们有一个标题,一个部分和一个结尾。该部分本身具有部分标题,部分详细信息和部分预告片。我需要在两个级别上合并两个文件-首先在部分级别,然后在部分详细信息级别。我希望我的结果基于第一个文件(标题和结尾将来自第一个文件)。如果节匹配,则需要保留第一个文件中节详细信息的排序(没有排序键,仅是出现的顺序)。如果第一个文件中没有该节,则需要从第二个文件中添加整个节。
我有xsl,可以给我结果,但顺序不正确。我需要有关如何订购它们的帮助。我没有尝试键查找,因为我不确定如何解释第一个文件中没有的部分。 当SectionDetails匹配时,我需要第一个文件中的记录出现在第二个文件中的记录之前。
我的第一个文件FileA在这里
<FileRecord>
<HeaderRecord>
<A>FileA</A>
</HeaderRecord>
<SectionRecord Subject="Science">
<SectionHeader>
<A>FileA</A>
</SectionHeader>
<SectionDetails Stream="Physics">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Chemistry">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Biology">
<A>FileA</A>
</SectionDetails>
<SectionTrailer>
<A>FileA</A>
</SectionTrailer>
</SectionRecord>
<SectionRecord Subject="Math">
<SectionHeader>
<A>FileA</A>
</SectionHeader>
<SectionDetails Stream="Algebra">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Calculus">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Geometry">
<A>FileA</A>
</SectionDetails>
<SectionTrailer>
<A>FileA</A>
</SectionTrailer>
</SectionRecord>
<TrailerRecord>
<A>FileA</A>
</TrailerRecord>
</FileRecord>
第二个文件FileB在这里
<FileRecord>
<HeaderRecord>
<A>FileB</A>
</HeaderRecord>
<SectionRecord Subject="Science">
<SectionHeader>
<A>FileB</A>
</SectionHeader>
<SectionDetails Stream="Chemistry">
<A>FileB</A>
</SectionDetails>
<SectionTrailer>
<A>FileB</A>
</SectionTrailer>
</SectionRecord>
<SectionRecord Subject="Math">
<SectionHeader>
<A>FileB</A>
</SectionHeader>
<SectionDetails Stream="Geometry">
<A>FileB</A>
</SectionDetails>
<SectionTrailer>
<A>FileB</A>
</SectionTrailer>
</SectionRecord>
<SectionRecord Subject="History">
<SectionHeader>
<A>FileB</A>
</SectionHeader>
<SectionDetails Stream="Ancient">
<A>FileB</A>
</SectionDetails>
<SectionDetails Stream="Modern">
<A>FileB</A>
</SectionDetails>
<SectionTrailer>
<A>FileB</A>
</SectionTrailer>
</SectionRecord>
<TrailerRecord>
<A>FileB</A>
</TrailerRecord>
</FileRecord>
我正在使用的xsl在这里
<xsl:stylesheet version="2.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xsd xsi xsl"
>
<xsl:param name="filebrecs" select="document('FileB.xml')"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="FileRecord"/>
</xsl:template>
<xsl:template match="FileRecord">
<FileRecord>
<xsl:apply-templates select="HeaderRecord"/>
<xsl:for-each-group select="SectionRecord, $filebrecs/FileRecord/SectionRecord" group-by="@Subject">
<SectionRecord>
<xsl:attribute name="Subject"><xsl:value-of select="current-grouping-key()"/> </xsl:attribute>
<xsl:apply-templates select="current-group()[1]/SectionHeader"/>
<xsl:for-each-group select="current-group()//SectionDetails" group-by="@Stream">
<xsl:for-each select="current-group()">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:for-each-group>
<xsl:apply-templates select="current-group()[1]/SectionTrailer"/>
</SectionRecord>
</xsl:for-each-group>
<xsl:apply-templates select="TrailerRecord"/>
</FileRecord>
</xsl:template>
</xsl:stylesheet>
我期望这样的结果
<FileRecord>
<HeaderRecord>
<A>FileA</A>
</HeaderRecord>
<SectionRecord Subject="Science">
<SectionHeader>
<A>FileA</A>
</SectionHeader>
<SectionDetails Stream="Physics">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Chemistry">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Chemistry">
<A>FileB</A>
</SectionDetails>
<SectionDetails Stream="Biology">
<A>FileA</A>
</SectionDetails>
<SectionTrailer>
<A>FileA</A>
</SectionTrailer>
</SectionRecord>
<SectionRecord Subject="Math">
<SectionHeader>
<A>FileA</A>
</SectionHeader>
<SectionDetails Stream="Algebra">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Calculus">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Geometry">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Geometry">
<A>FileB</A>
</SectionDetails>
<SectionTrailer>
<A>FileA</A>
</SectionTrailer>
</SectionRecord>
<SectionRecord Subject="History">
<SectionHeader>
<A>FileB</A>
</SectionHeader>
<SectionDetails Stream="Ancient">
<A>FileB</A>
</SectionDetails>
<SectionDetails Stream="Modern">
<A>FileB</A>
</SectionDetails>
<SectionTrailer>
<A>FileB</A>
</SectionTrailer>
</SectionRecord>
<TrailerRecord>
<A>FileA</A>
</TrailerRecord>
</FileRecord>
我得到的实际结果是
<?xml version = '1.0' encoding = 'UTF-8'?>
<FileRecord>
<HeaderRecord>
<A>FileA</A>
</HeaderRecord>
<SectionRecord Subject="Science">
<SectionHeader>
<A>FileA</A>
</SectionHeader>
<SectionDetails Stream="Physics">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Chemistry">
<A>FileB</A>
</SectionDetails>
<SectionDetails Stream="Chemistry">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Biology">
<A>FileA</A>
</SectionDetails>
<SectionTrailer>
<A>FileA</A>
</SectionTrailer>
</SectionRecord>
<SectionRecord Subject="Math">
<SectionHeader>
<A>FileA</A>
</SectionHeader>
<SectionDetails Stream="Geometry">
<A>FileB</A>
</SectionDetails>
<SectionDetails Stream="Geometry">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Algebra">
<A>FileA</A>
</SectionDetails>
<SectionDetails Stream="Calculus">
<A>FileA</A>
</SectionDetails>
<SectionTrailer>
<A>FileA</A>
</SectionTrailer>
</SectionRecord>
<SectionRecord Subject="History">
<SectionHeader>
<A>FileB</A>
</SectionHeader>
<SectionDetails Stream="Ancient">
<A>FileB</A>
</SectionDetails>
<SectionDetails Stream="Modern">
<A>FileB</A>
</SectionDetails>
<SectionTrailer>
<A>FileB</A>
</SectionTrailer>
</SectionRecord>
<TrailerRecord>
<A>FileA</A>
</TrailerRecord>
</FileRecord>
在“主题=科学”部分中,物理,化学和生物学的顺序正确无误,但我希望FileA记录出现在FileB记录之前。在“数学”部分的记录中,“几何”出现在“代数”和“微积分”之前。我希望它按FileA的顺序出现(并且FileA记录出现在FileB记录之前)。为什么它搞乱了数学而不是科学的顺序?
我也不喜欢使用硬编码访问第一个文件记录
<xsl:apply-templates select="current-group()[1]/SectionHeader"/>
有更好的方法吗?
答案 0 :(得分:0)
我试图重现您的错误,但我的输出与您想要的结果相符。
使用FileA.xml
作为第一个输入文件:
transform.xslt FileA.xml
和FileB.xml
作为XSLT中的第二个输入文件:
<xsl:param name="filebrecs" select="document('FileB.xml')"/>
然后您的输出将如预期的那样。
答案 1 :(得分:0)
尝试更改
<xsl:for-each-group select="current-group()//SectionDetails" group-by="@Stream">
<xsl:for-each select="current-group()">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:for-each-group>
到
<xsl:for-each-group select="for $rec in current-group() return $rec/SectionDetails" group-by="@Stream">
<xsl:apply-templates select="current-group()"/>
</xsl:for-each-group>
在处理来自不同文档的节点时,使用for return
表达式应保留外部总体的顺序,而如果使用current-group()//SectionDetails
,则表达式是不确定的和不可预测的。
为简化<xsl:apply-templates select="current-group()[1]/SectionHeader"/>
,在for-each-group
内部,每个组的第一项是上下文项,因此您可以简单地使用current-group()[1]
来代替.
,例如./SectionHeader
,当然可以缩短为SectionHeader
,即<xsl:apply-templates select="SectionHeader"/>
但是不确定为什么要使用for-each-group
之类的XSLT 2构造,然后在另一个答案的注释中提及Xalan,它是XSLT 1处理器,不支持for-each-group
。