比较两个元素以在xslt 2.0中设置当前节点

时间:2013-03-31 15:28:05

标签: xslt-2.0

我是xslt的新手所以请原谅这是一个天真的问题。我需要将源文档中包含部门名称的元素的值与另一个文档中的子元素的值相匹配,该文档将该部门名称的变体列为子项,并将该子项的父项设置为当前节点获得其他孩子的价值。

以下是源文档的示例:

<sourceRoot>
 <sourceElement>foo</sourceElement>
</sourceRoot>

以下是列表文档的示例:

<departments>
 <department>
  <child1>bar</child1>
  <child2>bar2</child2>
  <child3>bar3</child3>
 </department>
 <department>
  <child1>baz</child1>
  <child2>baz2</child2>
  <child3>baz3</child3>
 </department>
 <department>
  <child1>foo</child1>
  <child2>foo2</child2>
  <child3>foo3</child3>
 </department>
</departments>
etc.

这是理想的结果:

<child2value>foo2</child2value>
<child3value>foo3</child3value>

我尝试过使用这个xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    >

    <xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="UTF-8"/>
    <xsl:preserve-space elements="text"/>

    <xsl:variable name="departments" select="document('dept.xml')/departments"/>  

    <xsl:template match="/">          
        <xsl:variable name="sourceElement" select="sourceRoot/sourceElement"/>                   
        <xsl:variable name="child1" select="$departments/department/child1"/> 
        <xsl:variable name="child2" select="$departments/department/child2"/>
        <xsl:variable name="child3" select="$departments/department/child3"/>

        <xsl:choose>    
        <xsl:when test="$sourceElement=$child1">               
            <child2value>
                <xsl:value-of select="$departments/department[.]/child2"/>
            </child2value>
            <child3value>
                <xsl:value-of select="$departments/department[.]/child3"/>                
            </child3value>
        </xsl:when>
        <xsl:otherwise/>
    </xsl:choose>   
    </xsl:template>   
</xsl:stylesheet>

但它返回所有department个节点的子值。

<child2value>bar2 baz2 foo2</child2value>
<child3value>bar3 baz3 foo3</child3value>

我知道我在这里错过了关于如何将节点设置为当前的关键概念。感谢您对这位新手的任何建议。

2 个答案:

答案 0 :(得分:0)

我会按如下方式解决:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs">

<xsl:param name="dep-url" as="xs:string" select="'test2013033102.xml'"/>
<xsl:variable name="dep-doc" as="document-node()" select="doc($dep-url)"/>

<xsl:output method="xml" indent="yes" />

<xsl:key name="by-child" match="department" use="*"/>

<xsl:template match="/">
  <xsl:variable name="source" as="element(sourceElement)*" select="sourceRoot/sourceElement"/>
  <xsl:apply-templates select="key('by-child', $source, $dep-doc)/*[not(. = $source)]"/>
</xsl:template>

<xsl:template match="department/*">
  <xsl:element name="{name()}value">
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

将您的输入转换为

<?xml version="1.0" encoding="UTF-8"?>
<child2value>foo2</child2value>
<child3value>foo3</child3value>

答案 1 :(得分:0)

您可以通过单个XPath表达式选择所需内容,如此转换所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="sourceElement">
     <xsl:copy-of select=
     "document('file:///c:/temp/delete/dept.xml')
               /*/*[child1 = current()]
                     /*[not(self::child1)]
     "/>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<sourceRoot>
 <sourceElement>foo</sourceElement>
</sourceRoot>

,第二个提供的XML文档位于c:\temp\delete\dept.xml的本地文件系统中:

<departments>
 <department>
  <child1>bar</child1>
  <child2>bar2</child2>
  <child3>bar3</child3>
 </department>
 <department>
  <child1>baz</child1>
  <child2>baz2</child2>
  <child3>baz3</child3>
 </department>
 <department>
  <child1>foo</child1>
  <child2>foo2</child2>
  <child3>foo3</child3>
 </department>
</departments>

产生了想要的正确结果:

<child2>foo2</child2>
<child3>foo3</child3>

<强>更新

如果我们想要更改上面所选元素的名称,这非常简单:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="sourceElement">
     <xsl:apply-templates select=
     "document('file:///c:/temp/delete/dept.xml')
               /*/*[child1 = current()]
                     /*[not(self::child1)]
     "/>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'child')]">
  <xsl:element name="{name()}value"><xsl:value-of select="."/></xsl:element>
 </xsl:template>
</xsl:stylesheet>

<强>产生

<child2value>foo2</child2value>
<child3value>foo3</child3value>