我在转换此XML时遇到问题
<?xml version="1.0"?>
<Report username="TONYB" sessionId="20140425154921">
<Result>
<Request Type="InventoryShip">
.... Omitted for brevity
</Request>
<Information>
.... Omitted for brevity
</Information>
<Inventory>
<Sku>PBM118-00</Sku>
<RevisionNo/>
<OnHand>34010</OnHand>
.... Omitted for brevity
</Inventory>
<Inventory>
<Sku>PFC00345</Sku>
<RevisionNo/>
<OnHand>0</OnHand>
.... Omitted for brevity
</Inventory>
<Inventory>
<Sku>PFC00476</Sku>
<RevisionNo/>
<OnHand>2025</OnHand>
.... Omitted for brevity
</Inventory>
<Item>
<Sku>PBM118-00</Sku>
<CustomerPart>CP-0004</CustomerPart>
<Description>PACKING SLIP GE-M CHANGED XX WITH A LONG DESC</Description>
<Groups>
<Group>BOOK</Group>
.... Omitted for brevity
<Group>HR</Group>
.... Omitted for brevity
</Groups>
.... Omitted for brevity
<LowestUOM>EA</LowestUOM>
</Item>
<Item>
<Sku>PFC00345</Sku>
<CustomerPart>1001</CustomerPart>
<Description>item description 8/29/2011 16:06</Description>
<Groups>
<Group>F60</Group>
<Group>FAKE2</Group>
<Group>HR</Group>
<Group>TYPE</Group>
</Groups>
.... Omitted for brevity
<LowestUOM>EA</LowestUOM>
</Item>
<Item>
<Sku>PFC00476</Sku>
<CustomerPart>PBM119-88</CustomerPart>
<Description>PBM118-99 NEW ITEM</Description>
<Groups>
<Group>BOOK</Group>
<Group>HR</Group>
</Groups>
.... Omitted for brevity
<LowestUOM>EA</LowestUOM>
</Item>
<Usage>
.... Omitted for brevity
</Usage>
<Usage>
<DateRange>
<Start>01/01/2014</Start>
<End>12/31/2014</End>
</DateRange>
<OrderedBySku>
<Sku>PBM118-00</Sku>
<ShippedQty>951</ShippedQty>
<User/>
</OrderedBySku>
<OrderedBySku>
<Sku>PFC00476</Sku>
<ShippedQty>0</ShippedQty>
<User/>
</OrderedBySku>
</Usage>
<Usage>
<DateRange>
<End>12/31/2014</End>
</DateRange>
<OrderedBySku>
<Sku>PFC00476</Sku>
<ShippedQty>0</ShippedQty>
<User/>
</OrderedBySku>
<OrderedBySku>
<Sku>PBM118-00</Sku>
<ShippedQty>116668</ShippedQty>
<User/>
</OrderedBySku>
</Usage>
</Result>
</Report>
就像这样,第一个“Group”字段的每次转换之间都有一个空行:
<html>
..... Omitted for brevity
<tbody>
<tr class="">
<td><img src="/wmsImages/SALIX/products/PBM118-00_THM.jpg"></td><td>CP-0004</td><td>PACKING SLIP GE-M CHANGED XX WITH A LONG DESC</td><td>U</td><td>Y</td><td class="number">34,010EA</td><td class="number">116,668</td><td class="number">100CA</td><td>BOOK</td><td>CORP</td><td>FAKE</td><td>FAKE2</td><td>FAKE3</td><td>FAKEDEPT</td><td>HR</td><td>REPORT</td><td>fake</td><td></td><td></td>
</tr>
<tr class="">
<td></td><td>PBM119-88</td><td>PBM118-99 NEW ITEM</td><td>U</td><td>Y</td><td class="number">2,025EA</td><td class="number">0</td><td class="number">EA</td><td>BOOK</td><td>HR</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr class="">
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr class="">
<td></td><td>1001</td><td>item description 8/29/2011 16:06</td><td>U</td><td>Y</td><td class="number">0EA</td><td class="number">0</td><td class="number">10RL</td><td>F60</td><td>FAKE2</td><td>HR</td><td>TYPE</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr class="">
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
</tbody>
..... Omitted for brevity
</html>
我一直这样:
<html>
..... Omitted for brevity
<tbody>
<tr class="">
<td><img src="/wmsImages/SALIX/products/PBM118-00_THM.jpg"></td><td>CP-0004</td><td>PACKING SLIP GE-M CHANGED XX WITH A LONG DESC</td><td>U</td><td>Y</td><td class="number">34,010EA</td><td class="number">116,668</td><td class="number">100CA</td><td>BOOK</td><td>CORP</td><td>FAKE</td><td>FAKE2</td><td>FAKE3</td><td>FAKEDEPT</td><td>HR</td><td>REPORT</td><td>fake</td><td></td><td></td>
</tr>
<tr class="">
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr class="">
<td></td><td>PBM119-88</td><td>PBM118-99 NEW ITEM</td><td>U</td><td>Y</td><td class="number">2,025EA</td><td class="number">0</td><td class="number">EA</td><td>BOOK</td><td>HR</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr class="">
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr class="">
<td></td><td>1001</td><td>item description 8/29/2011 16:06</td><td>U</td><td>Y</td><td class="number">0EA</td><td class="number">0</td><td class="number">10RL</td><td>F60</td><td>FAKE2</td><td>HR</td><td>TYPE</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr class="">
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
</tbody>
..... Omitted for brevity
</html>
所以我做错了什么。是的,“Group”标签是可选的,我们可以有0或更多。但在这种情况下,正如您所看到的,所有3个项目的第一组列中都有一些内容。
这是我的xslt:
<?xml version='1.0' encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="report_common.xsl"/>
<xsl:param name="csvLink" />
<xsl:param name="thumbs" />
<xsl:param name="showOutOfStock" select="'Yes'"/>
<xsl:variable name="xxshowRevision" select="'Junk'" />
<xsl:variable name="ThumbNames" select="document($thumbs)"/>
<xsl:variable name="maxGroupCols" select="10"/>
<!-- Define a rule to suppress header elements. -->
<xsl:template mode="header"
match="BelowLowPoint|Discontinued|Inactive|OrderStatus|Sku|DateRange">
</xsl:template>
<!-- Define the root template for this report. -->
<xsl:template match="/Report">
<html>
<head>
<title>Inventory with Shipping Data</title>
<meta http-equiv="Content-Type"
content="text/html"/>
<link href="/css/layout.css"
rel="stylesheet" type="text/css" />
<link href="/css/markup.css"
rel="stylesheet" type="text/css" />
<link href="/css/printer.css"
rel="stylesheet" type="text/css" media='printer' />
<link href="/css/SALIX.css"
rel="stylesheet" type="text/css" />
<style type="text/css">
.OutOfStock{
background-color: red
}
</style>
</head>
<body>
<form action="">
<input type="button" class="cssbutton no-print"
onClick="window.print()"
value="Print Screen"/>
</form>
<xsl:apply-templates select="Result"/>
<div class="no-print">
<xsl:element name="form">
<xsl:attribute name="name" >csvForm</xsl:attribute>
<xsl:attribute name="method">post</xsl:attribute>
<xsl:attribute name="action">
<xsl:value-of select="concat('/staticreports/',$csvLink)"/>
</xsl:attribute>
<input type="hidden" name="reportType"
value="StaticReport"/>
<xsl:element name="input">
<xsl:attribute name="type">hidden</xsl:attribute>
<xsl:attribute name="name">reportTitle</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="$reportTitle"/>
</xsl:attribute>
</xsl:element>
<a href="#"
onClick="document.csvForm.submit();return false"
>Click here to export into spreadsheet.</a>
</xsl:element>
</div>
</body>
</html>
</xsl:template>
<xsl:key name="byGroup" match="Inventory" use="../Item/Sku[.=current()/Sku]/../Groups/Group[1]" />
<xsl:template match="Result">
<xsl:apply-imports/>
<table class="report data">
<col class="itemNo"/>
<thead>
<tr>
<td/>
<th>Client Lit Code #</th>
<th>Description</th>
<xsl:if test="$xxshowRevision='Yes'">
<th>Revision</th>
</xsl:if>
<th>ACC CDE</th>
<th>Allow Web</th>
<th class="number">Available Balance</th>
<th class="number">Total Shipped</th>
<th class="number">UOM</th>
<xsl:call-template name="groupHead">
<xsl:with-param name="i">1</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$maxGroupCols"/>
</xsl:with-param>
</xsl:call-template>
</tr>
</thead>
<tbody>
<xsl:for-each select="Inventory[ count(. | key( 'byGroup', '../Item/Sku[.=current()/Sku]/../Groups/Group[1]')[1]) = 1 ]">
<xsl:sort select="../Item/Sku[.=current()/Sku]/../Groups"/>
<xsl:sort select="../Item/Sku[.=current()/Sku]/../CustomerPart"/>
<xsl:sort select="Sku"/>
<xsl:sort select="RevisionNo"/>
<xsl:variable name="Item"
select="../Item[./Sku=current()/Sku]"/>
<xsl:element name="tr">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="position()!=last() and position() mod 5 = 0"
>bgLight </xsl:when>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select="." mode="item"/>
</xsl:element>
<xsl:element name="tr">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="position()!=last() and position() mod 5 = 0"
>bgLight </xsl:when>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select="." mode="group" />
</xsl:element>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
<!-- Define a rule for each inventory group -->
<xsl:template match="Inventory" mode="group">
<td></td> <!-- ThumbImage -->
<td></td> <!-- PartNo -->
<td></td> <!-- Description -->
<xsl:if test="$xxshowRevision='Yes'">
<td></td> <!-- RevisionNo -->
</xsl:if>
<td></td> <!-- Access -->
<td></td> <!-- Web -->
<td></td> <!-- OnHand, LowestUOM -->
<td></td> <!-- OrderedBySku -->
<td></td> <!-- UomQty, UOM -->
<xsl:call-template name="emptyGroupCols">
<xsl:with-param name="i">1</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$maxGroupCols"/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<!-- Define a rule for each inventory item -->
<xsl:template match="Inventory" mode="item">
<xsl:variable name="Item"
select="../Item[./Sku=current()/Sku]"/>
<xsl:variable name="Revision"
select="../Revision[./Sku=current()/Sku and
./RevisionNo=current()/RevisionNo]"/>
<xsl:variable name="CustPart"
select="normalize-space($Item/CustomerPart)"/>
<xsl:variable name="PartNo">
<xsl:choose>
<xsl:when test="string-length($CustPart)>0">
<xsl:value-of select="$CustPart"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="Sku"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Date format must be MM/DD/YYYY to work! -->
<xsl:variable name="Year2Date"
select="../Usage[starts-with(DateRange/Start, '01/01/')]
[starts-with(DateRange/End, '12/31/')]"/>
<xsl:variable name="Month2Date"
select="../Usage[DateRange/Start != $Year2Date/DateRange/Start or
DateRange/End != $Year2Date/DateRange/End ]
[substring(DateRange/Start, 1, 3) =
substring(DateRange/End, 1, 3)]"/>
<xsl:variable name="AllDates"
select="../Usage[not(DateRange/Start)]
[starts-with(DateRange/End, '12/31/')]"/>
<xsl:variable name="SkuThumbImage"
select=" $ThumbNames/ThumbList/ThumbFile[@Item=$Item/Sku]/File"/>
<xsl:variable name="ThumbImage">
<xsl:choose>
<xsl:when test="string-length($SkuThumbImage)>0">
<xsl:value-of select="$SkuThumbImage"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select=" $ThumbNames/ThumbList/ThumbFile[@Item=$Item/CustomerPart]/File"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="UOM">
<xsl:choose>
<xsl:when test="string-length(normalize-space($Item/UOM))>0">
<xsl:value-of select="$Item/UOM"/>
</xsl:when>
<xsl:when test="string-length(normalize-space($Item/LowestUOM))>0">
<xsl:value-of select="$Item/LowestUOM"/>
</xsl:when>
<xsl:otherwise>EA</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="LowestUOM">
<xsl:choose>
<xsl:when test="string-length(normalize-space($Item/LowestUOM))>0">
<xsl:value-of select="$Item/LowestUOM"/>
</xsl:when>
<xsl:otherwise>EA</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<td><xsl:if test="normalize-space($ThumbImage) != ''">
<xsl:element name="img">
<xsl:attribute name="src">
<xsl:text>/wmsImages/SALIX/products/</xsl:text>
<xsl:value-of select="$ThumbImage" />
</xsl:attribute>
</xsl:element>
</xsl:if></td>
<td><xsl:value-of select="$PartNo"/></td>
<td><xsl:value-of select="$Item/Description"/></td>
<xsl:if test="$xxshowRevision='Yes'">
<td><xsl:value-of select="RevisionNo"/></td>
</xsl:if>
<td><xsl:value-of select="$Item/Access"/></td>
<td><xsl:value-of select="$Item/Web"/></td>
<td class='number'><xsl:value-of
select="concat( format-number(OnHand,$rptqty,'f0'), $LowestUOM )"/></td>
<td class='number'><xsl:value-of
select="format-number(sum($AllDates/OrderedBySku
[Sku=current()/Sku]/ShippedQty),
$rptqty,'f0')"/></td>
<td class='number'><xsl:value-of
select="concat( $Item/UomQty, $UOM )"/></td>
<xsl:variable name="countGroup"
select="count($Item/Groups/Group )"/>
<xsl:variable name="useNumGroupCols">
<xsl:choose>
<xsl:when test="$countGroup >= $maxGroupCols">
<xsl:value-of select="$maxGroupCols"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$countGroup"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:for-each select="$Item/Groups/Group">
<xsl:if test="position() <= $useNumGroupCols">
<td><xsl:value-of select="."/></td>
</xsl:if>
</xsl:for-each>
<xsl:if test="$maxGroupCols > $useNumGroupCols">
<xsl:call-template name="emptyGroupCols">
<xsl:with-param name="i">
<xsl:value-of select="$useNumGroupCols"/>
</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$maxGroupCols"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="emptyGroupCols">
<xsl:param name="i" />
<xsl:param name="count" />
<xsl:if test="$i <= $count">
<td></td>
</xsl:if>
<!--begin_: RepeatTheLoopUntilFinished-->
<xsl:if test="$i <= $count">
<xsl:call-template name="emptyGroupCols">
<xsl:with-param name="i">
<xsl:value-of select="$i + 1"/>
</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$count"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="groupHead">
<xsl:param name="i" />
<xsl:param name="count" />
<xsl:if test="$i <= $count">
<th>Group <xsl:value-of select="$i"/></th>
</xsl:if>
<!--begin_: RepeatTheLoopUntilFinished-->
<xsl:if test="$i <= $count">
<xsl:call-template name="groupHead">
<xsl:with-param name="i">
<xsl:value-of select="$i + 1"/>
</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$count"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
感谢您提供任何帮助。
编辑(2014年4月28日): Here is a zip包含所有必需的文件,或try here if non-zip更容易。请注意,“StaticFormatcsv.xsl”文件还有其他问题,我只包含它,因为它在我运行的命令中被引用。你现在可以忽略它。一旦我修复了主xsl,我将对“csv”xsl应用相同的修复。
此外,这是我运行的命令:
java -cp /usr/share/java/xalan.jar org.apache.xalan.xslt.Process -in StaticData20140425154921 -out StaticReport20140425154921.html -PARAM csvLink StaticReport20140425154921.csv -PARAM thumbs ThumbList.xsl -xsl StaticFormat.xsl
其中“xalan.jar”指/指向“xalan-2.4.1.jar”。
答案 0 :(得分:0)
我开始简化您的XSLT ....
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Report">
<html>
<head>
<title>Inventory with Shipping Data</title>
</head>
<body>
<xsl:apply-templates select="Result"/>
</body>
</html>
</xsl:template>
<xsl:key name="byGroup" match="Inventory" use="../Item/Sku[.=current()/Sku]/../Groups/Group[1]" />
<xsl:template match="Result">
<table class="report data">
<tbody>
<xsl:for-each select="Inventory[ count(. | key( 'byGroup', '../Item/Sku[.=current()/Sku]/../Groups/Group[1]')[1]) = 1 ]">
<xsl:element name="tr">
<xsl:apply-templates select="." mode="item"/>
</xsl:element>
<xsl:element name="tr">
<xsl:apply-templates select="." mode="group" />
</xsl:element>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
<xsl:template match="Inventory" mode="item">
<td><xsl:value-of select="../Item/Sku[.=current()/Sku]/../Groups/Group[1]" /></td>
</xsl:template>
<xsl:template match="Inventory" mode="group">
<td><xsl:value-of select="Sku" /></td>
</xsl:template>
</xsl:stylesheet>
首先要注意的是,对于XML中的每个 Inventory 元素,您输出两个 tr 元素,这就是您在输出中获得六行的原因。你总是以这种方式得到偶数行。也许你想要的是为每个不同的项目/组/组[1] 输出一行(其中有两个不同的值),然后为每个库存<输出一行/ strong>哪个匹配 Sku 。
首先,您的密钥可以简化为此
<xsl:key name="byGroup" match="Inventory"
use="../Item[Sku=current()/Sku]/Groups/Group[1]" />
但是如何使用此密钥存在问题...
<xsl:for-each
select="Inventory[ count(. | key( 'byGroup', '../Item/Sku[.=current()/Sku]/../Groups/Group[1]')[1]) = 1 ]">
您不应该使用撇号作为键函数的第二个参数,否则它将被视为文字。你应该这样做....(使用上面显示的简化键)
<xsl:for-each
select="Inventory[ count(. | key( 'byGroup', ../Item[Sku=current()/Sku]/Groups/Group[1])[1]) = 1 ]">
但即便如此也存在问题。在 xsl:key 语句中,当前()将引用当前匹配的广告资源项。但是在 xsl:for-each 语句中,当前()指的是 xsl:for-each 已执行,即结果元素。
要解决此问题,请定义一个键,以便您通过 Sku
查找项元素<xsl:key name="itemBySku" match="Item" use="Sku" />
然后, xsl:for-each 可以这样写:
<xsl:for-each
select="Inventory[ count(. | key('byGroup', key('itemBySku', Sku)/Groups/Group[1])[1]) = 1 ]">
最后,要输出当前组中的所有广告资源元素,您可以执行以下操作:
<xsl:apply-templates
select="key('byGroup', key('itemBySku', Sku)/Groups/Group[1])" mode="group" />
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Report">
<html>
<head>
<title>Inventory with Shipping Data</title>
</head>
<body>
<xsl:apply-templates select="Result"/>
</body>
</html>
</xsl:template>
<xsl:key name="byGroup" match="Inventory" use="../Item[Sku=current()/Sku]/Groups/Group[1]" />
<xsl:key name="itemBySku" match="Item" use="Sku" />
<xsl:template match="Result">
<table class="report data">
<tbody>
<xsl:for-each select="Inventory[ count(. | key('byGroup', key('itemBySku', Sku)/Groups/Group[1])[1]) = 1 ]">
<tr>
<xsl:apply-templates select="." mode="item"/>
</tr>
<xsl:apply-templates select="key('byGroup', key('itemBySku', Sku)/Groups/Group[1])" mode="group" />
</xsl:for-each>
</tbody>
</table>
</xsl:template>
<xsl:template match="Inventory" mode="item">
<td><xsl:value-of select="key('itemBySku', Sku)/Groups/Group[1]" /></td>
</xsl:template>
<xsl:template match="Inventory" mode="group">
<tr>
<td><xsl:value-of select="Sku" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
这可能实际上并不是你想要的,但它至少应该告诉你如何简化你的XSLT,并给你一些东西作为添加你需要的所有其他功能的基础。与手头的潜在问题有关。