我收到一个设计不佳的 CSV 文件,如下所示(此处过于简化):
BizTalk 转换为 XML,但“详细信息”行上缺少“标题”值。我现在需要创建另一个文件,在其中将仪表和状态“下移”到具有卷数据的行。 XML 看起来像这样。
<VendorFile xmlns="http://etc/VendorFile">
<Row xmlns="">
<Meter>123</Meter>
<State>TX</State>
<StartDate/>
<Volume/>
</Row>
<Row xmlns="">
<Meter></Meter>
<State></State>
<StartDate>1/1/2024</StartDate>
<Volume>100</Volume>
</Row>
<Row xmlns="">
<Meter></Meter>
<State></State>
<StartDate>1/2/2024</StartDate>
<Volume>110</Volume>
</Row>
<Row xmlns="">
<Meter></Meter>
<State></State>
<StartDate>1/3/2024</StartDate>
<Volume>107</Volume>
</Row>
<Row xmlns="">
<Meter>456</Meter>
<State>OK</State>
<StartDate/>
<Volume/>
</Row>
<Row xmlns="">
<Meter></Meter>
<State></State>
<StartDate>1/1/2024</StartDate>
<Volume>200</Volume>
</Row>
<Row xmlns="">
<Meter></Meter>
<State></State>
<StartDate>1/2/2024</StartDate>
<Volume>205</Volume>
</Row>
<Row xmlns="">
<Meter></Meter>
<State></State>
<StartDate>1/3/2024</StartDate>
<Volume>210</Volume>
</Row>
</VendorFile>
所需的输出将如下所示(但字段名称不同,因为我将其映射到另一个内部规范模式)并发送到我们的第三方软件系统之一。
<VendorFile xmlns="http://etc/VendorFile">
<Row xmlns="">
<Meter>123</Meter>
<State>TX</State>
<StartDate>1/1/2024</StartDate>
<Volume>100</Volume>
</Row>
<Row xmlns="">
<Meter>123</Meter>
<State>TX</State>
<StartDate>1/2/2024</StartDate>
<Volume>110</Volume>
</Row>
<Row xmlns="">
<Meter>123</Meter>
<State>TX</State>
<StartDate>1/3/2024</StartDate>
<Volume>107</Volume>
</Row>
<Row xmlns="">
<Meter>456</Meter>
<State>OK</State>
<StartDate>1/1/2024</StartDate>
<Volume>200</Volume>
</Row>
<Row xmlns="">
<Meter>456</Meter>
<State>OK</State>
<StartDate>1/2/2024</StartDate>
<Volume>205</Volume>
</Row>
<Row xmlns="">
<Meter>456</Meter>
<State>OK</State>
<StartDate>1/3/2024</StartDate>
<Volume>210</Volume>
</Row>
</VendorFile>
到目前为止我的 XSLT 看起来像这样:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0" version="1.0" xmlns:ns0="http://etc/GasMeasurementDataCanonical" xmlns:s0="http://etc/VendorFile">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="/s0:VendorFile" />
</xsl:template>
<xsl:template match="/s0:VendorFile">
<ns0:GasMeasurementDataCanonical>
<xsl:for-each select="Row[StartDate[text()!='']]">
<Row>
<Meter_Number>
<xsl:value-of select="preceding-sibling::Meter[text()!='']" />
</Meter_Number>
<On_Date_Time>
<xsl:value-of select="StartDate/text()" />
</On_Date_Time>
...
对于 Meter_Number - 我想要第一个前面的兄弟(按向后顺序),其中 Meter 不是空字符串。
我从这个开始:
<xsl:for-each select="Row[StartDate[text()!='']]">
这样就可以正确地拉出有卷的行。 现在我需要回头去拿仪表。
这些是我尝试过的一些变化:
<xsl:value-of select="preceding-sibling::Meter[text()!='']" />
<xsl:value-of select="../preceding-sibling::Meter[text()!='']" />
<xsl:value-of select="/*preceding-sibling::Meter[text()!='']" />
是否可以做我想做的事情,以及如何修复 select 语句?
我建议使用
for-each-group group-starting-with
例如
<xsl:for-each-group select="//Row" group-starting-with="Row[normalize-space(Meter) and normalize-space(State)]">
<xsl:apply-templates select="tail(current-group())"/>
</xsl:for-each-group>
然后与
<xsl:template match="Row">
<xsl:copy>
<xsl:apply-templates select="current-group()[1]!(Meter, State), *"/>
</xsl:copy>
</xsl:template>
您可以转换每行以包含“组标题”中的
Meter
和 State
信息。我已经使用了 xsl:copy
,但您当然可以使用文字结果元素来创建需要将 Row
转换为的任何元素。
失败的主要原因是您的
Row
元素没有名为 Meter
的前同级元素。你想要preceding-sibling::Row/Meter
。
谓词
text()!=''
也是错误的。如果一个元素为空,则它没有文本节点;文本节点本身的长度永远不会为零。要测试元素是否为空,请使用谓词 [. != '']
.