XML / XSL:xpath 和条件 when/otherwise
XML / XSL : xpath and condition when/otherwise
我的 xsl 转换有问题。
这是 XML:
<?xml version="1.0" encoding="windows-1252"?>
<accounts>
<account>
<name>ryan</name>
<pass>password</pass>
<date></date>
<numbers>
<number>19</number>
</numbers>
<numbers>
<number>2</number>
</numbers>
<numbers>
<number>20</number>
</numbers>
</account>
<account>
<name>lift</name>
<pass>azerty</pass>
<date>27/05/2015</date>
<numbers>
</numbers>
</account>
</accounts>
这是 XSL:
<?xml version="1.0" encoding="windows-1252"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<xsl:output method="xml" indent="yes" encoding="windows-1252"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="newline">
<xsl:text/>
</xsl:variable>
<xsl:template match="/">
<accounts>
<xsl:for-each select="accounts/account">
<account>
<xsl:for-each select="*[not(self::numbers)]">
<xsl:choose>
<xsl:when test="count(*|text()[string-length(normalize-space(.))>0])">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:attribute name="xsi:nil">true</xsl:attribute>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:call-template name="t_number"/>
</account>
</xsl:for-each>
</accounts>
</xsl:template>
<xsl:template name="t_number" match="numbers">
<xsl:choose>
<xsl:when test="count(number)">
<numbers>
<xsl:for-each select="numbers/number">
<number>
<xsl:value-of select="." />
</number>
</xsl:for-each>
</numbers>
</xsl:when>
<xsl:otherwise>
<numbers xsi:nil="true"></numbers>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这是我所拥有的:
<?xml version="1.0" encoding="windows-1252"?>
<accounts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<account>
<name>ryan</name>
<pass>password</pass>
<date xsi:nil="true">
</date>
<numbers xsi:nil="true"></numbers>
</account>
<account>
<name>lift</name>
<pass>azerty</pass>
<date>27/09/2012</date>
<numbers xsi:nil="true"></numbers>
</account>
</accounts>
我想要的是:
<?xml version="1.0" encoding="windows-1252"?>
<accounts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<account>
<name>ryan</name>
<pass>password</pass>
<date xsi:nil="true">
</date>
<numbers>
<number>19</number>
<number>2</number>
<number>20</number>
</numbers>
</account>
<account>
<name>lift</name>
<pass>azerty</pass>
<date>27/09/2012</date>
<numbers xsi:nil="true"></numbers>
</account>
</accounts>
你能帮帮我吗?计数函数以一种奇怪的方式工作。
表达式的上下文节点
<xsl:when test="count(number)">
错了。当通过 <xsl:call-template name="t_number"/>
调用时,您仍然在 account
中。所以,
<xsl:when test="count(numbers/number) gt 0">
应该可以解决问题。 (我更喜欢 "gt 0",因为在我看来它更具可读性。)
编辑: 据我所知,模板 "t_numbers" 仅通过 <xsl:call-template name="t_number"/>
调用一次。可能,你最好删除 match="numbers"
以避免混淆。
这样怎么样?
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<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="/accounts">
<accounts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:apply-templates select="@*|node()"/>
</accounts>
</xsl:template>
<xsl:template match="account">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::numbers)]"/>
<numbers>
<xsl:choose>
<xsl:when test="numbers/number">
<xsl:apply-templates select="numbers/number"/>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="xsi:nil">true</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</numbers>
</xsl:copy>
</xsl:template>
<xsl:template match="date[not(string())]">
<date xsi:nil="true"/>
</xsl:template>
</xsl:stylesheet>
注:
可以删除模板匹配 "/accounts"
,结果在语义上将完全相同。
我的 xsl 转换有问题。
这是 XML:
<?xml version="1.0" encoding="windows-1252"?>
<accounts>
<account>
<name>ryan</name>
<pass>password</pass>
<date></date>
<numbers>
<number>19</number>
</numbers>
<numbers>
<number>2</number>
</numbers>
<numbers>
<number>20</number>
</numbers>
</account>
<account>
<name>lift</name>
<pass>azerty</pass>
<date>27/05/2015</date>
<numbers>
</numbers>
</account>
</accounts>
这是 XSL:
<?xml version="1.0" encoding="windows-1252"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<xsl:output method="xml" indent="yes" encoding="windows-1252"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="newline">
<xsl:text/>
</xsl:variable>
<xsl:template match="/">
<accounts>
<xsl:for-each select="accounts/account">
<account>
<xsl:for-each select="*[not(self::numbers)]">
<xsl:choose>
<xsl:when test="count(*|text()[string-length(normalize-space(.))>0])">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:attribute name="xsi:nil">true</xsl:attribute>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:call-template name="t_number"/>
</account>
</xsl:for-each>
</accounts>
</xsl:template>
<xsl:template name="t_number" match="numbers">
<xsl:choose>
<xsl:when test="count(number)">
<numbers>
<xsl:for-each select="numbers/number">
<number>
<xsl:value-of select="." />
</number>
</xsl:for-each>
</numbers>
</xsl:when>
<xsl:otherwise>
<numbers xsi:nil="true"></numbers>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这是我所拥有的:
<?xml version="1.0" encoding="windows-1252"?>
<accounts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<account>
<name>ryan</name>
<pass>password</pass>
<date xsi:nil="true">
</date>
<numbers xsi:nil="true"></numbers>
</account>
<account>
<name>lift</name>
<pass>azerty</pass>
<date>27/09/2012</date>
<numbers xsi:nil="true"></numbers>
</account>
</accounts>
我想要的是:
<?xml version="1.0" encoding="windows-1252"?>
<accounts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<account>
<name>ryan</name>
<pass>password</pass>
<date xsi:nil="true">
</date>
<numbers>
<number>19</number>
<number>2</number>
<number>20</number>
</numbers>
</account>
<account>
<name>lift</name>
<pass>azerty</pass>
<date>27/09/2012</date>
<numbers xsi:nil="true"></numbers>
</account>
</accounts>
你能帮帮我吗?计数函数以一种奇怪的方式工作。
表达式的上下文节点
<xsl:when test="count(number)">
错了。当通过 <xsl:call-template name="t_number"/>
调用时,您仍然在 account
中。所以,
<xsl:when test="count(numbers/number) gt 0">
应该可以解决问题。 (我更喜欢 "gt 0",因为在我看来它更具可读性。)
编辑: 据我所知,模板 "t_numbers" 仅通过 <xsl:call-template name="t_number"/>
调用一次。可能,你最好删除 match="numbers"
以避免混淆。
这样怎么样?
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<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="/accounts">
<accounts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:apply-templates select="@*|node()"/>
</accounts>
</xsl:template>
<xsl:template match="account">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::numbers)]"/>
<numbers>
<xsl:choose>
<xsl:when test="numbers/number">
<xsl:apply-templates select="numbers/number"/>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="xsi:nil">true</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</numbers>
</xsl:copy>
</xsl:template>
<xsl:template match="date[not(string())]">
<date xsi:nil="true"/>
</xsl:template>
</xsl:stylesheet>
注:
可以删除模板匹配 "/accounts"
,结果在语义上将完全相同。