检查子节点是否存在并应用模板
我有以下简化的 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>
我必须检查
元素是否存在。如果不存在
元素,则必须中止映射,否则每个
需要一个
元素被创建。
我想出了这个到目前为止效果很好的解决方案:
<?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>
如果有
元素,则输出是这样的:
<?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>
如果只有
并且没有
映射被中止。
现在我有两个问题:
- 我对
元素的测试是否可靠:test="not(ExportData/DataSet/Tables/Table/Rows/node())"?
-我使用
创建
项,而不是
代码>构造。我的 XPath 表达式还可以吗?或者我可以改进它们吗?
I have the following simplified XML structure:
<?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>
I have to check if <R>
elements exist or not. If no <R>
elements exist the mapping has to be aborted, otherwise a <Line>
element per <R>
needs to be created.
I came up with this solution which works perfectly so far:
<?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>
If there are <R>
elements the output is this:
<?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>
If there is just <Rows/>
and no <R>
s the mapping is aborted.
Now I have two questions:
-Is my test for <R>
elements robust: test="not(ExportData/DataSet/Tables/Table/Rows/node())"
?
-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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,您是否希望它在没有
R
元素时失败,或者在Rows
没有子node()
时失败,这将包括任何元素(不仅仅是R
)、text()
、comment()
或processing - 指令()?
如果您确实想验证是否至少有一个
R
元素是Rows
的子元素,您应该将测试标准调整得更具体:< /strong>否则,它可能会通过该测试并继续处理,但不会生成您想要的内容。
您可以删除根节点模板内的
条件逻辑,并将该逻辑移至不包含的Rows
模板中R
孩子。将逻辑放入xsl:template
@match
标准中可以使 XSLT 处理器更容易优化,从而提高性能。Well, do you want it to fail if there are no
R
elements, or fail ifRows
does not have a childnode()
, which would include any element (not justR
),text()
,comment()
orprocessing-instruction()
?If you really want to verify that there is at least one
R
element that is a child ofRows
, you should adjust the test criteria to be more specific:Otherwise, it may pass that test and continue processing and not generate the content you want.
You could get rid of the
<xsl:if>
conditional logic inside of your template for the root node and move that logic into a template forRows
that don't containR
children. Putting logic intoxsl:template
@match
criteria makes it easier for XSLT processors to optimize, which can lead to performance gains.这将检查 R 节点是否有子元素:
This will check whether R node has child element: