我正在使用XSLT,它具有使用(MySegment/*[not(.=preceding::*)]).
输入:
<MySegment>
<Field1>ABCD</Field1>
<FIeld2>1</Field2>
</MySegment>
<MySegment>
<Field1>ABCD123</Field1>
<FIeld2>1</Field2>
</MySegment>
这里我们有两个不同的值,但是由于ABCD123也包含ABCD,因此它被视为重复条目。任何人都可以提供建议。
以下是我的XSLT的样子:
<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:template match="/RecordsInp">
<xsl:for-each select="ParentSegment">
<xsl:for-each select="./MySegment/*[not(.=preceding::*)]">
<A>
<Field1><xsl:value-of select ="name(.)"/></Field1>
<Field2><xsl:value-of select="."/></Field2>
</A>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我的意见是:
<RecordsInp>
<ParentSegment>
<MySegment>
<Field1>ABC</Field1>
<Field2>A1</Field2>
</MySegment>
<MySegment>
<Field1>ABC</Field1>
<Field2>A1</Field2>
</MySegment>
<MySegment>
<Field1>ABCDEF</Field1>
<Field2>ABC</Field2>
</MySegment>
</ParentSegment>
</RecordsInp>
我得到的是:
<?xml version="1.0" encoding="UTF-8"?>
<A>
<Field1>Field1</Field1>
<Field2>ABC</Field2>
</A><A>
<Field1>Field2</Field1>
<Field2>A1</Field2>
</A><A>
<Field1>Field1</Field1>
<Field2>ABCDEF</Field2>
</A>
注意我在最后一次出现时没有得到Field2 = ABC。由于Field2在之前的事件中从未有过ABC,我需要在XML下面:
<?xml version="1.0" encoding="UTF-8"?>
<A>
<Field1>Field1</Field1>
<Field2>ABC</Field2>
</A><A>
<Field1>Field2</Field1>
<Field2>A1</Field2>
</A><A>
<Field1>Field1</Field1>
<Field2>ABCDEF</Field2>
</A>
<A>
<Field1>Field2</Field1>
<Field2>ABC</Field2>
</A>
答案 0 :(得分:0)
根据您的第二个输入示例,您的样式表未按预期方式提取<Field2>ABC</Field2>
的原因是因为ABC
作为前一个Field1
中的值存在。
你还可以根据谓词中的当前(current()
)名称测试名称,但也许你应该尝试使用xsl:key
(Muenchian grouping)而不是preceding::
轴...
XML输入
<RecordsInp>
<ParentSegment>
<MySegment>
<Field1>ABC</Field1>
<Field2>A1</Field2>
</MySegment>
<MySegment>
<Field1>ABC</Field1>
<Field2>A1</Field2>
</MySegment>
<MySegment>
<Field1>ABCDEF</Field1>
<Field2>ABC</Field2>
</MySegment>
</ParentSegment>
</RecordsInp>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="fields" match="MySegment/*"
use="concat(name(),'|',normalize-space())"/>
<xsl:template match="MySegment">
<xsl:for-each
select="*[count(.|key('fields',concat(name(),'|',normalize-space()))[1])=1]">
<A>
<Field1><xsl:value-of select="name()"/></Field1>
<Field2><xsl:value-of select="."/></Field2>
</A>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
<A>
<Field1>Field1</Field1>
<Field2>ABC</Field2>
</A>
<A>
<Field1>Field2</Field1>
<Field2>A1</Field2>
</A>
<A>
<Field1>Field1</Field1>
<Field2>ABCDEF</Field2>
</A>
<A>
<Field1>Field2</Field1>
<Field2>ABC</Field2>
</A>
答案 1 :(得分:0)
您的XPath表达式./MySegment/*[not(.=preceding::*)]
选择每个上下文节点的<MySegment>
个子元素的子元素,这些子元素的字符串值与文档顺序中的任何元素的字符串值不匹配。因此,由于前面的<Field2>ABC</Field2>
元素,<Field1>ABC</Field1>
未反映在结果中。
显然,这是一个比你想要的更广泛的条件;据我所知,你只想比较具有相同名称的前面的元素。在纯XPath中表达有点棘手;使用样式表重构更容易处理。无端使用xsl:for-each
表明了这种重构。这是一个合理的方法:
<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="*"/>
<xsl:template match="/RecordsInp/ParentSegment/MySegment/*">
<!-- bind the context node's name and value to variables: -->
<xsl:variable name="fname" select="name()"/>
<xsl:variable name="fvalue" select="string(.)"/>
<!-- here's the test you seem really to want: -->
<xsl:if test="not(preceding::*[name() = $fname and string() = $fvalue])">
<A>
<Field1><xsl:value-of select ="$fname"/></Field1>
<Field2><xsl:value-of select="$fvalue"/></Field2>
</A>
</xsl:if>
</xsl:template>
</xsl:stylesheet>