所以我的xml看起来像这样
<Data>
<History>
<z r="1" c1="BILL" c2="123" c3="02/20/2006" c4="100.00" c5=".00" c6=".00" c7="100.00" c8=".00" c9=".00" c10=".00" lcdesc="BILL"/>
<z r="2" c1="PAYCODE" c2="456" c3="03/16/2006" c4="-100.00" c5=".00" c6=".00" c7="-100.00" c8=".00" c9=".00" c10=".00" lcdesc="PAYMENT"/>
<z r="3" c1="Total" c2="123" c3="02/20/2006" c4=".00" c5=".00" c6=".00" c7=".00" c8=".00" c9=".00" c10=".00" lcdesc="Total"/>
<z r="4" lcdesc=""/>
<z r="5" c1="BILL" c2="124" c3="03/27/2006" c4="13000.00" c5="400.00" c6=".00" c7="13400.00" c8=".00" c9=".00" c10=".00" lcdesc="BILL"/>
<z r="6" c1="PAYCODE" c2="457" c3="04/13/2006" c4="-13000.00" c5="-400.00" c6=".00" c7="-13400.00" c8=".00" c9=".00" c10=".00" lcdesc="PAYMENT"/>
<z r="7" c1="Total" c2="124" c3="03/27/2006" c4=".00" c5=".00" c6=".00" c7=".00" c8=".00" c9=".00" c10=".00" lcdesc="Total"/>
<z r="8" lcdesc=""/>
<z r="9" c1="BILL" c2="125" c3="04/28/2006" c4="1000.00" c5=".00" c6=".00" c7="1000.00" c8=".00" c9=".00" c10=".00" lcdesc="BILL"/>
<z r="10" c1="PAYCODE" c2="458" c3="05/10/2006" c4="-1000.00" c5=".00" c6=".00" c7="-1000.00" c8=".00" c9=".00" c10=".00" lcdesc="PAYMENT"/>
<z r="11" c1="Total" c2="125" c3="04/28/2006" c4=".00" c5=".00" c6=".00" c7=".00" c8=".00" c9=".00" c10=".00" lcdesc="Total"/>
<z r="12" lcdesc=""/>
</History>
</Data>
我想从c1 =&#34; BILL&#34;中提取一些信息。后续行上的z节点。我想获得发票号(c2)和发票日期(c3)。所以我在我的模板中想到,如果c1 =&#39; BILL&#39;那么我会声明一个变量并对当前节点进行选择。或者前面的兄弟,其中c1 =&#39; BILL&#39;。虽然它适用于第一个节点及其后续行,但在第二个帐单行上它会放置先前的帐单行信息。所以有些事情是对的。你能帮忙吗?
这是我的非工作xslt:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
<xsl:output indent="no"/>
<xsl:template match="/">
<History>
<xsl:apply-templates select="//History/z"/>
</History>
</xsl:template>
<xsl:template match="/PageData/History/z">
<xsl:variable name="invnode" select="current()[@c1 = 'BILL'] | preceding-sibling::z[@c1 = 'BILL'][1]" />
<z>
<xsl:for-each select="@*">
<!--get the attribute name-->
<xsl:variable name="nodename">
<xsl:value-of select="name()"/>
</xsl:variable>
<xsl:attribute name="{$nodename}"><xsl:value-of select="."/></xsl:attribute>
</xsl:for-each>
<xsl:attribute name="invoice"><xsl:value-of select="$invnode/@c2" /></xsl:attribute>
<xsl:if test="string-length($invnode/@c3) >= 10">
<xsl:attribute name="invdate1"><xsl:value-of select="concat(substring($invnode/@c3, 7), substring($invnode/@c3, 1, 2), substring($invnode/@c3, 4, 2))" /></xsl:attribute>
<xsl:attribute name="invdate2"><xsl:value-of select="concat(substring($invnode/@c3, 7), '-', substring($invnode/@c3, 1, 2), '-', substring($invnode/@c3, 4, 2))" /></xsl:attribute>
</xsl:if>
</z>
</xsl:template>
</xsl:stylesheet>
我想要的输出如下:
<Data>
<History>
<z r="1" c1="BILL" c2="123" c3="02/20/2006" c4="100.00" c5=".00" c6=".00" c7="100.00" c8=".00" c9=".00" c10=".00" lcdesc="BILL" invoice="123" invdate1="20060220" invdate2="2006-02-20" />
<z r="2" c1="PAYCODE" c2="456" c3="03/16/2006" c4="-100.00" c5=".00" c6=".00" c7="-100.00" c8=".00" c9=".00" c10=".00" lcdesc="PAYMENT" invoice="123" invdate1="20060220" invdate2="2006-02-20" />
<z r="3" c1="Total" c2="123" c3="02/20/2006" c4=".00" c5=".00" c6=".00" c7=".00" c8=".00" c9=".00" c10=".00" lcdesc="Total" invoice="123" invdate1="20060220" invdate2="2006-02-20" />
<z r="4" lcdesc="" invoice="123" invdate1="20060220" invdate2="2006-02-20" />
<z r="5" c1="BILL" c2="124" c3="03/27/2006" c4="13000.00" c5="400.00" c6=".00" c7="13400.00" c8=".00" c9=".00" c10=".00" lcdesc="BILL" invoice="124" invdate1="20060327" invdate2="2006-03-27" />
<z r="6" c1="PAYCODE" c2="457" c3="04/13/2006" c4="-13000.00" c5="-400.00" c6=".00" c7="-13400.00" c8=".00" c9=".00" c10=".00" lcdesc="PAYMENT" invoice="124" invdate1="20060327" invdate2="2006-03-27" />
<z r="7" c1="Total" c2="124" c3="03/27/2006" c4=".00" c5=".00" c6=".00" c7=".00" c8=".00" c9=".00" c10=".00" lcdesc="Total" invoice="124" invdate1="20060327" invdate2="2006-03-27" />
<z r="8" lcdesc="" invoice="124" invdate1="20060327" invdate2="2006-03-27" />
<z r="9" c1="BILL" c2="125" c3="04/28/2006" c4="1000.00" c5=".00" c6=".00" c7="1000.00" c8=".00" c9=".00" c10=".00" lcdesc="BILL" invoice="125" invdate1="20060428" invdate2="2006-04-28" />
<z r="10" c1="PAYCODE" c2="458" c3="05/10/2006" c4="-1000.00" c5=".00" c6=".00" c7="-1000.00" c8=".00" c9=".00" c10=".00" lcdesc="PAYMENT" invoice="125" invdate1="20060428" invdate2="2006-04-28" />
<z r="11" c1="Total" c2="125" c3="04/28/2006" c4=".00" c5=".00" c6=".00" c7=".00" c8=".00" c9=".00" c10=".00" lcdesc="Total" invoice="125" invdate1="20060428" invdate2="2006-04-28" />
<z r="12" lcdesc="" invoice="125" invdate1="20060428" invdate2="2006-04-28" />
</History>
</Data>
答案 0 :(得分:2)
以这种方式试试吗?
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="z">
<xsl:variable name="invnode" select="current()[@c1='BILL'] | preceding-sibling::z[@c1 = 'BILL'][1][not(current()/@c1='BILL')]" />
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:attribute name="invoice">
<xsl:value-of select="$invnode/@c2" />
</xsl:attribute>
<xsl:attribute name="invdate1">
<xsl:value-of select="concat(substring($invnode/@c3, 7), substring($invnode/@c3, 1, 2), substring($invnode/@c3, 4, 2))" />
</xsl:attribute>
<xsl:attribute name="invdate2">
<xsl:value-of select="concat(substring($invnode/@c3, 7), '-', substring($invnode/@c3, 1, 2), '-', substring($invnode/@c3, 4, 2))" />
</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<强>解释强>
这个表达式:
current()[@c1='BILL']
选择当前节点,前提是当前节点是发票;否则它返回一个空节点集。
这个表达式:
preceding-sibling::z[@c1 = 'BILL'][1][not(current()/@c1='BILL')]"
返回最近的作为发票的在前兄弟,前提是当前节点不是发票;否则它返回一个空节点集。
因此,在这两个表达式的并集中,其中一个子集将始终为空:
如果当前节点是发票,则左侧返回当前节点,右侧为空。
如果当前节点不是发票,则左侧为空,右侧返回最近的前一个兄弟,即发票。
因此,union只会包含一个节点,并且顺序没有意义。
答案 1 :(得分:2)
怎么样......
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" >
<xsl:output indent="yes" omit-xml-declaration="yes" encoding="utf8" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="z">
<z invoice="{(.|preceding-sibling::z)[@c1='BILL'][last()]/@c2}">
<xsl:apply-templates select="(.|preceding-sibling::z)[@c1='BILL'][last()]/@c3" mode="inv-date" />
<xsl:apply-templates select="@*|node()"/>
</z>
</xsl:template>
<xsl:template match="@c3" mode="inv-date" />
<xsl:template match="@c3[string-length(.) >= 10]" mode="inv-date">
<xsl:attribute name="invdate1"><xsl:value-of select="concat(substring(., 7), substring(., 1, 2), substring(., 4, 2))" /></xsl:attribute>
<xsl:attribute name="invdate2"><xsl:value-of select="concat(substring(., 7), '-', substring(., 1, 2), '-', substring(., 4, 2))" /></xsl:attribute>
</xsl:template>
</xsl:stylesheet>