[英]XSLT-2.0 IF statement/grouping
我是XSLT和XML的新手,并试图使用XSLT从XML文件创建CSV。 我有大量的学院数据,涉及某些年份,他们发表了不同类型的内容,例如书籍,书籍中的章节,期刊文章等,我希望将它们制成表格,以显示每年每种出版物的数量。所以:
Year, 1990, 1993, 1995, 1994, .....2017, 2018
Book, 1,3,0,0,...1,1
Journal Article, 2,1,0,1,...1,1
Book Chapter, 1, 1,0,0,...0,0
如您所见,对于他们没有任何特定类型的出版物的年份,我想将其强制为零。 我能够将其绘制成不带零的形式绘制它们,但是出于数据目的,我想强制使用它。 这是我们的XML文档的格式:
<?xml version="1.0" encoding="UTF-8"?>
<Data xmlns="http://www.digitalmeasures.com/schema/data" xmlns:dmd="http://www.digitalmeasures.com/schema/data-metadata" dmd:date="2017-10-16">
<Record userId="1898739" username="50019019" termId="5923" dmd:surveyId="17683692">
<dmd:IndexEntry indexKey="COLLEGE" entryKey="College of Engineering" text="College of Engineering"/>
<dmd:IndexEntry indexKey="DEPARTMENT" entryKey="Civil, Architectural, & Environmental Engineering" text="Civil, Architectural, & Environmental Engineering"/>
<INTELLCONT id="151368386560" dmd:originalSource="MANAGE_DATA" dmd:lastModified="2017-10-03T10:47:54" dmd:startDate="2016-01-01" dmd:endDate="2016-12-31">
<REFEREED>Yes</REFEREED>
<CONTYPE>Journal Article</CONTYPE>
<CONTYPEOTHER/>
<STATUS>Published</STATUS>
<TITLE>Sample data</TITLE>
<TITLE_SECONDARY/>
<INTELLCONT_AUTH id="151368386563">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="151368386561">
<FACULTY_NAME>1898739</FACULTY_NAME>
<FNAME>sample</FNAME>
<MNAME>sample</MNAME>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<PUBLISHER>sample</PUBLISHER>
<PUBCTYST/>
<PUBCNTRY/>
<VOLUME>13</VOLUME>
<ISSUE>11</ISSUE>
<PAGENUM>117</PAGENUM>
<WEB_ADDRESS/>
<DOI>sample</DOI>
<ISBNISSN/>
<PMCID/>
<AUDIENCE/>
<PUBLICAVAIL/>
<ABSTRACT/>
<FULL_TEXT/>
<DTM_EXPSUB/>
<DTD_EXPSUB/>
<DTY_EXPSUB/>
<EXPSUB_START></EXPSUB_START>
<EXPSUB_END></EXPSUB_END>
<DTM_SUB/>
<DTD_SUB/>
<DTY_SUB/>
<SUB_START></SUB_START>
<SUB_END></SUB_END>
<DTM_ACC/>
<DTD_ACC/>
<DTY_ACC/>
<ACC_START></ACC_START>
<ACC_END></ACC_END>
<DTM_PUB/>
<DTD_PUB/>
<DTY_PUB>2016</DTY_PUB>
<PUB_START>2016-01-01</PUB_START>
<PUB_END>2016-12-31</PUB_END>
<USER_REFERENCE_CREATOR>Yes</USER_REFERENCE_CREATOR>
</INTELLCONT>
<INTELLCONT dmd:originalSource="IMPORT" dmd:lastModified="2017-10-03T11:17:33" dmd:startDate="2016-01-01" dmd:endDate="2016-12-31">
<REFEREED>Yes</REFEREED>
<CONTYPE>Journal Article</CONTYPE>
<CONTYPEOTHER/>
<STATUS>Published</STATUS>
<TITLE>Sample</TITLE>
<TITLE_SECONDARY/>
<INTELLCONT_AUTH id="141176756225">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756226">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756227">
<FACULTY_NAME>1898739</FACULTY_NAME>
<FNAME>sample</FNAME>
<MNAME>sample</MNAME>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756228">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME>sample</MNAME>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756229">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756230">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>sample</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756231">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756232">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756233">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME>sample</MNAME>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756234">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<INTELLCONT_AUTH id="141176756235">
<FACULTY_NAME/>
<FNAME>sample</FNAME>
<MNAME/>
<LNAME>sample</LNAME>
<INSTITUTION/>
<ROLE>Author</ROLE>
<STUDENT_LEVEL/>
</INTELLCONT_AUTH>
<PUBLISHER>sample</PUBLISHER>
<PUBCTYST/>
<PUBCNTRY/>
<VOLUME>23</VOLUME>
<ISSUE/>
<PAGENUM>2003-2013</PAGENUM>
<WEB_ADDRESS/>
<DOI>sample</DOI>
<ISBNISSN/>
<PMCID/>
<AUDIENCE/>
<PUBLICAVAIL/>
<ABSTRACT/>
<FULL_TEXT/>
<DTM_EXPSUB/>
<DTD_EXPSUB/>
<DTY_EXPSUB/>
<EXPSUB_START></EXPSUB_START>
<EXPSUB_END></EXPSUB_END>
<DTM_SUB/>
<DTD_SUB/>
<DTY_SUB/>
<SUB_START></SUB_START>
<SUB_END></SUB_END>
<DTM_ACC/>
<DTD_ACC/>
<DTY_ACC/>
<ACC_START></ACC_START>
<ACC_END></ACC_END>
<DTM_PUB/>
<DTD_PUB/>
<DTY_PUB>2016</DTY_PUB>
<PUB_START>2016-01-01</PUB_START>
<PUB_END>2016-12-31</PUB_END>
<USER_REFERENCE_CREATOR>Yes</USER_REFERENCE_CREATOR>
</INTELLCONT>
</Record> <!-- Added by edit -->
</Data> <!-- Added by edit -->
出于明显的原因,所有机密信息已被单词“ sample”代替,但这不应影响逻辑。 因此,我当前的XSLT多年来一直在打印,然后是类似的文章类型:
Type
Journal Article,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,
,1,3,3,1,2,1,2,3,8,2,12,11,5,6,10,11,4,5,4,7,10,4,
Book,1995,2006,2008,2011,
,1,1,1,1,
Book Chapter,2005,2006,2008,2011,2015,2016,
,1,3,3,2,1,1,
Abstract,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,
,8,22,12,6,13,9,6,18,5,3,4,2,7,1,
Other,2004,2005,2006,2007,2008,
,2,3,2,2,8,
Total,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,
,1,1,3,3,1,2,1,2,3,25,38,34,19,31,17,17,32,10,8,8,11,19,6,
这是XSLT-2.0供参考:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:csv="csv:csv"
xmlns="http://www.w3.org/1999/xhtml" xmlns:dm="http://www.digitalmeasures.com/schema/data"
xmlns:dmd="http://www.digitalmeasures.com/schema/data-metadata"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:xhtml="http://www.w3.org/1999/xhtml" exclude-result-prefixes="array fn map math xhtml xs">
<xsl:output method="text" encoding="utf-8"/>
<xsl:variable name="delimiter" select="','"/>
<!-- xmlns:dm is the xmlns attribute in Data.-->
<xsl:template match="/dm:Data">
<xsl:text>Type</xsl:text>
<xsl:text>
</xsl:text>
<!--Journal Article Publications-->
<xsl:text>Journal Article,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Journal Article']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="(current-grouping-key())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Journal Article']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="count(current-group())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<!-- Book Publications -->
<xsl:text>Book,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Book']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="(current-grouping-key())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Book']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="count(current-group())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<!--Book Chapter Publications-->
<xsl:text>Book Chapter,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Book Chapter']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="(current-grouping-key())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Book Chapter']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="count(current-group())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<!--Abstract Publications-->
<xsl:text>Abstract,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Abstract']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="(current-grouping-key())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Abstract']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="count(current-group())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<!--Other Publications-->
<xsl:text>Other,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Other']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="(current-grouping-key())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT[dm:CONTYPE='Other']" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="count(current-group())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text>Total,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="(current-grouping-key())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:text>,</xsl:text>
<xsl:for-each-group select="dm:Record/dm:INTELLCONT" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:value-of select="count(current-group())" />
<xsl:text>,</xsl:text>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
因此,我认为我需要在代码中包含某种If语句,以便仅打印所有年份,然后在某些类型的出版物不存在的年份中强制为零。
这是某种逻辑上听起来像我的伪代码:
<xsl:for-each-group select="dm:Record/dm:INTELLCONT" group-by="dm:DTY_PUB">
<xsl:sort select="current-grouping-key()" />
<xsl:if test = "dm:Record/dm:INTELLCONT/dm:CONTYPE != 'Book'"> //if the type of content is not of Book, print zero for that year
print ("0,")
else: <xsl:value-of select="count(current-group())" /> <xsl:text>,</xsl:text> // otherwise, print the number of Books published that year.
</xsl:if>
</xsl:for-each-group>
如果我的问题不清楚,请告诉我。
我花了大量时间试图使它尽可能清晰。
我想我们不需要样本中的所有这些元素,听起来您有一个子元素可以提供类型或类别的分组依据,并且您有一年的时间。 所以我创建了一些更简单的样本数据
<?xml version="1.0" encoding="UTF-8"?>
<root>
<items>
<item>
<category>a</category>
<year>2000</year>
</item>
<item>
<category>a</category>
<year>2017</year>
</item>
<item>
<category>a</category>
<year>2000</year>
</item>
<item>
<category>b</category>
<year>1999</year>
</item>
<item>
<category>b</category>
<year>2018</year>
</item>
<item>
<category>b</category>
<year>1999</year>
</item>
<item>
<category>b</category>
<year>2000</year>
</item>
</items>
</root>
和XSLT 3样式表(可以与Saxon 9.8所有版本一起使用),使用组合键可以按类别和年份标识一组项目。 使用min
和max
函数可以简单地创建年份列表。 所以用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="xs math"
version="3.0">
<xsl:output method="text"/>
<xsl:key name="cat-year" match="items/item" composite="yes" use="category, xs:integer(year)"/>
<xsl:variable name="input-doc" select="."/>
<xsl:template match="/">
<xsl:variable name="min-year" as="xs:integer" select="min(root/items/item/year/xs:integer(.))"/>
<xsl:variable name="max-year" as="xs:integer" select="max(root/items/item/year/xs:integer(.))"/>
<xsl:variable name="categories" select="distinct-values(root/items/item/category)"/>
<xsl:variable name="years" as="xs:integer*" select="$min-year to $max-year"/>
<xsl:value-of select="$years" separator=","/>
<xsl:text> </xsl:text>
<xsl:for-each select="$categories">
<xsl:variable name="cat" select="."/>
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
<xsl:value-of select="$years!count(key('cat-year', ($cat, .), $input-doc))" separator=","/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我懂了
1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018
a
0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0
b
2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
尝试使其适应您的XML格式。 让我们知道您是可以使用XSLT 3还是被XSLT 2所困扰,在这种情况下,您可以定义一个将类别和年份连接在一起的键,其余代码应相同:
<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="text"/>
<xsl:key name="cat-year" match="items/item" use="concat(category, '|', year)"/>
<xsl:variable name="input-doc" select="."/>
<xsl:template match="/">
<xsl:variable name="min-year" as="xs:integer" select="min(root/items/item/year/xs:integer(.))"/>
<xsl:variable name="max-year" as="xs:integer" select="max(root/items/item/year/xs:integer(.))"/>
<xsl:variable name="categories" select="distinct-values(root/items/item/category)"/>
<xsl:variable name="years" as="xs:integer*" select="$min-year to $max-year"/>
<xsl:value-of select="$years" separator=","/>
<xsl:text> </xsl:text>
<xsl:for-each select="$categories">
<xsl:variable name="cat" select="."/>
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
<xsl:value-of select="for $y in $years return count(key('cat-year', concat($cat, '|', $y), $input-doc))" separator=","/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
@Martin Honnen发布了一个效果很好的解决方案,我将其应用到了我自己的问题中,下面是代码,以防有人希望看到它如何特别适用于我的情况:
<xsl:key name="Contype-Year" match="dm:Data/dm:Record/dm:INTELLCONT" use="concat(dm:CONTYPE, '|', dm:DTY_PUB)"/>
<xsl:variable name="input-doc" select="."/>
<xsl:template match="/">
<xsl:variable name="min-year" as="xs:integer" select="min(dm:Data/dm:Record/dm:INTELLCONT/dm:DTY_PUB/xs:integer(.))"/>
<xsl:variable name="max-year" as="xs:integer" select="max(dm:Data/dm:Record/dm:INTELLCONT/dm:DTY_PUB/xs:integer(.))"/>
<xsl:variable name="categories" select="distinct-values(dm:Data/dm:Record/dm:INTELLCONT/dm:CONTYPE)"/>
<xsl:variable name="years" as="xs:integer*" select="$min-year to $max-year"/>
<xsl:value-of select="$years" separator=","/>
<xsl:text> </xsl:text>
<xsl:for-each select="$categories">
<xsl:variable name="cat" select="."/>
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
<xsl:value-of select="for $y in $years return count(key('Contype-Year', concat($cat, '|', $y), $input-doc))" separator=","/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.