我正试图为其他人解决这个问题并且自己遇到了一个问题。
我有XML:
<Process>
<name>Pro1</name>
<duration>Dur1</duration>
<time>Time1</time>
<name>Pro2</name>
<duration>Dur2</duration>
<time>Time2</time>
<name>Pro3</name>
<duration>Dur3</duration>
<time>Time3</time>
<name>Pro4</name>
<duration>Dur4</duration>
<time>Time4</time>
<name>Pro5</name>
<duration>Dur5</duration>
<time>Time5</time>
</Process>
输出:
<Process>
<Process_Info>
<name>Pro1</name>
<duration>Dur1</duration>
<time>Time1</time>
</Process_Info>
<Process_Info>
<name>Pro2</name>
<duration>Dur2</duration>
<time>Time2</time>
</Process_Info>
<Process_Info>
<name>Pro3</name>
<duration>Dur3</duration>
<time>Time3</time>
</Process_Info>
<Process_Info>
<name>Pro4</name>
<duration>Dur4</duration>
<time>Time4</time>
</Process_Info>
<Process_Info>
<name>Pro5</name>
<duration>Dur5</duration>
<time>Time5</time>
</Process_Info>
</Process>
使用XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name ="varProcess" select ="Process"/>
<xsl:template match="Process">
<xsl:element name="Process">
<xsl:for-each select ="name">
<xsl:variable name ="posName" select ="position()"/>
<xsl:element name ="Process_Info">
<xsl:copy-of select ="."/>
<xsl:copy-of select="$varProcess/duration[$posName]"/>
<xsl:copy-of select="$varProcess/time[$posName]"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
但是,<duration>
和<time>
节点并不总是存在,<name>
是唯一的保护节点。因此,如果遗失了一个,position()
选择失败。
即使<duration>
和/或<time>
不存在,如何更改XSLT以使其正常工作。
我的理论是你选择当前名称节点下面的两个节点,如果它们是<duration>
或<time>
,它们会被复制?但不确定如何实现。
导致问题的当前输出示例。
输入:
<Process>
<name>Pro1</name>
<duration>Dur1</duration>
<time>Time1</time>
<name>Pro2</name>
<duration>Dur2</duration>
<time>Time2</time>
<name>Pro3</name>
<duration>Dur3</duration>
<time>Time3</time>
<name>Pro4</name>
<time>Time4</time>
<name>Pro5</name>
<duration>Dur5</duration>
</Process>
输出:
<Process>
<Process_Info>
<name>Pro1</name>
<duration>Dur1</duration>
<time>Time1</time>
</Process_Info>
<Process_Info>
<name>Pro2</name>
<duration>Dur2</duration>
<time>Time2</time>
</Process_Info>
<Process_Info>
<name>Pro3</name>
<duration>Dur3</duration>
<time>Time3</time>
</Process_Info>
<Process_Info>
<name>Pro4</name>
<duration>Dur5</duration> <!-- Should be in the below process_info -->
<time>Time4</time>
</Process_Info>
<Process_Info>
<name>Pro5</name>
</Process_Info>
</Process>
答案 0 :(得分:2)
这就是诀窍,虽然方法中有点“手动”。可能有更优雅的方法来实现这个目标
<xsl:template match="Process">
<xsl:element name="Process">
<xsl:for-each select ="name">
<xsl:element name ="Process_Info">
<xsl:copy-of select ="."/>
<xsl:variable name="firstSib" select="local-name(following-sibling::*[1])" />
<xsl:variable name="secondSib" select="local-name(following-sibling::*[2])" />
<xsl:choose>
<xsl:when test="$firstSib='duration'">
<xsl:copy-of select="following-sibling::*[1]"/>
<xsl:choose>
<xsl:when test="$secondSib='time'">
<xsl:copy-of select="following-sibling::*[2]"/>
</xsl:when>
<xsl:otherwise>
<time>SomeDefaultValueForMissingTime</time>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$firstSib='time'">
<duration>SomeDefaultValueForMissingDuration</duration>
<xsl:copy-of select="following-sibling::*[1]"/>
</xsl:when>
<xsl:otherwise>
<duration>SomeDefaultValueForMissingDuration</duration>
<time>SomeDefaultValueForMissingTime</time>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
输入:
<Process>
<name>Pro1</name>
<duration>Dur1</duration>
<time>Time1</time>
<name>NameMissingDuration</name>
<time>TimeMissingDuration</time>
<name>NameMissingTime</name>
<duration>DurMissingTime</duration>
<name>NameMissingBoth</name>
<name>NormalName</name>
<duration>NormalDuration</duration>
<time>NormalTime</time>
</Process>
<强>输出强>
<Process>
<Process_Info>
<name>Pro1</name>
<duration>Dur1</duration>
<time>Time1</time>
</Process_Info>
<Process_Info>
<name>NameMissingDuration</name>
<duration>SomeDefaultValueForMissingDuration</duration>
<time>TimeMissingDuration</time>
</Process_Info>
<Process_Info>
<name>NameMissingTime</name>
<duration>DurMissingTime</duration>
<time>SomeDefaultValueForMissingTime</time>
</Process_Info>
<Process_Info>
<name>NameMissingBoth</name>
<duration>SomeDefaultValueForMissingDuration</duration>
<time>SomeDefaultValueForMissingTime</time>
</Process_Info>
<Process_Info>
<name>NormalName</name>
<duration>NormalDuration</duration>
<time>NormalTime</time>
</Process_Info>
</Process>
答案 1 :(得分:2)
这是一个没有xsl:if
的替代解决方案。
这演示了在选择第一个时间(或 duration )元素时使用generate-id()
函数测试节点相等性,该元素遵循当前的名称元素,其第一个名称元素是当前元素。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="Process">
<xsl:copy>
<xsl:apply-templates select="name"/>
</xsl:copy>
</xsl:template>
<xsl:template match="name">
<xsl:variable name="this" select="generate-id()"/>
<Process_Info>
<xsl:copy-of select="."/>
<xsl:copy-of select="following-sibling::duration
[generate-id(preceding-sibling::name[1]) = $this]
[1]"/>
<xsl:copy-of select="following-sibling::time
[generate-id(preceding-sibling::name[1]) = $this]
[1]"/>
</Process_Info>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
根据nonnb的反应,所有信用都归他所有,最终的XSLT正在被使用。我的错误是不包括我不需要填充节点的问题。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="Process">
<xsl:element name="Process">
<xsl:for-each select ="name">
<xsl:element name ="Process_Info">
<xsl:copy-of select ="."/>
<xsl:variable name="firstSib" select="local-name(following-sibling::*[1])" />
<xsl:variable name="secondSib" select="local-name(following-sibling::*[2])" />
<xsl:if test ="($firstSib='duration') or ($firstSib='time')">
<xsl:copy-of select="following-sibling::*[1]"/>
</xsl:if>
<xsl:if test ="($secondSib='duration') or ($secondSib='time')">
<xsl:copy-of select="following-sibling::*[2]"/>
</xsl:if>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>