我有以下简化的XML结构:
<?xml version="1.0" encoding="UTF-8"?>
<ExportData>
<TransportHeader>
<Timestamp>2011-01-16 06:00:33</Timestamp>
<From>
<Name>DynamicExport</Name>
<Version>1.</Version>
</From>
<MessageId>d7b5c5b69a83</MessageId>
</TransportHeader>
<ExportConfig>
<DateTimeFormat>yyyy-MM-dd HH:mm:ss</DateTimeFormat>
<DecimalSymbol>.</DecimalSymbol>
</ExportConfig>
<DataSet>
<Tables>
<Table>
<RH>...</RH>
<Rows>
<R>Data1</R>
<R>Data2</R>
<R>Data3</R>
<R>Data4</R>
<R>Data5</R>
</Rows>
</Table>
</Tables>
</DataSet>
</ExportData>
我必须检查是否存在<R>
个元素。如果不存在<R>
元素,则必须中止映射,否则需要创建每<Line>
个<R>
个元素。
我想出了这个迄今为止完美无缺的解决方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="ISO-8859-1" method="xml" indent="yes" />
<!-- suppress nodes that are not matched -->
<xsl:template match="text() | @*">
<xsl:apply-templates select="text() | @*"/>
</xsl:template>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="not(ExportData/DataSet/Tables/Table/Rows/node())">
<xsl:message terminate="yes">No line items</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/ExportData/DataSet/Tables/Table/Rows">
<INVOIC02>
<!-- apply LINE ITEMS template -->
<xsl:apply-templates select="R"/>
</INVOIC02>
</xsl:template>
<!-- Template creating LINE ITEMS -->
<xsl:template match="R">
<Line>
<elements></elements>
</Line>
</xsl:template>
</xsl:stylesheet>
如果有<R>
个元素,则输出为:
<?xml version="1.0" encoding="ISO-8859-1"?>
<INVOIC02>
<Line>
<elements/>
</Line>
<Line>
<elements/>
</Line>
<Line>
<elements/>
</Line>
<Line>
<elements/>
</Line>
<Line>
<elements/>
</Line>
</INVOIC02>
如果只有<Rows/>
且没有<R>
,则映射将被中止。
现在我有两个问题:
- 我对<R>
元素的测试是否健全:test="not(ExportData/DataSet/Tables/Table/Rows/node())"
?
- 我使用<xsl:apply-templates>
创建<Line>
项而不是<xsl:for-each>
构造。我的XPath表达式是否正常还是可以让它们变得更好?
感谢您对此提出的任何回复或建议。
祝你好运, 彼得
答案 0 :(得分:5)
我对元素的测试是否健壮:test =“not(ExportData / DataSet / Tables / Table / Rows / node())” ?
那么,如果没有R
元素,您希望它失败吗?如果Rows
没有子node()
,则会失败,其中包括任何元素< / em>(不只是R
),text()
,comment()
或processing-instruction()
?
如果您确实要验证至少有一个R
元素是Rows
的子元素,则应将测试条件调整为更具体:
test="not(ExportData/DataSet/Tables/Table/Rows/R)"
否则,它可能会通过该测试并继续处理,而不会生成您想要的内容。
I am using <xsl:apply-templates> to create the <Line> items instead of an <xsl:for-each> construct. Are my XPath expressions okay or could I make them better?
您可以删除模板中针对根节点的<xsl:if>
条件逻辑,并将该逻辑移动到不包含Rows
子项的R
模板中。将逻辑放入xsl:template
@match
条件可以使XSLT处理器更容易优化,从而提高性能。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="ISO-8859-1" method="xml" indent="yes" />
<!-- suppress nodes that are not matched -->
<xsl:template match="text() | @*">
<xsl:apply-templates select="text() | @*"/>
</xsl:template>
<!--All Rows must contain an R.
If we encounter any that do not, terminate the transform -->
<xsl:template match="/ExportData/DataSet/Tables/Table/Rows[not(R)]">
<xsl:message terminate="yes">No line items</xsl:message>
</xsl:template>
<!--match for Rows that have R children -->
<xsl:template match="/ExportData/DataSet/Tables/Table/Rows[R]">
<INVOIC02>
<!-- apply LINE ITEMS template -->
<xsl:apply-templates select="R"/>
</INVOIC02>
</xsl:template>
<!-- Template creating LINE ITEMS -->
<xsl:template match="R">
<Line>
<elements></elements>
</Line>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
请检查
<xsl:if test="R">
<!--What you want to do here-->
</xsl:if>
这将检查R节点是否具有子元素。
Buddhika