使用Custom XSLT映射多次出现的源

时间:2016-01-15 17:00:58

标签: xml xslt

我有一个源XML如下---

<Characteristics>
    <Cname>.....</Cname>
    <Cvalue>....</Cvalue>
</Characteristics>

现在上面的元素'特征'可能会多次出现。

然后我们有目标XML如下

<Parent>
  <elem_a/>
  <elem_b/>
  <elem_c/>
  <elem_d/>
     .
     .
     .
</Parent>

现在要求是,对于每次出现'特征',我们首先检查子元素'Cname'的值;给出的是,元素'Cname'的值将始终为'elem_a'或'elem_b'或'elem_c',所以......它们可以按任何顺序出现,如下所示---

<Characteristics>
    <Cname>elem_d</Cname>
    <Cvalue>123</Cvalue>
</Characteristics>
<Characteristics>
    <Cname>elem_a</Cname>
    <Cvalue>073</Cvalue>
</Characteristics>
       .
       .
       .

因此,当元素'Cname'的值为'elem_a'时,我们将元素'Cvalue'的值发送到目标元素'elem_a'

我试着按照以下方式前进,但后来我被卡住了。

<xsl:for-each select="Characteristics/node()[contains(local-name(),&apos;Cname&apos;)]">
<xsl:if test="contains(./text(),'elem_a')>
<Parent xmlns=" ">
    <elem_a xmlns=" ">
        <xsl:value-of select="Characteristics/Cvalue/text()"/>
    </elem_a>
</Parent>
</xsl:if>
</xsl:for-each>

在编写上面的代码之后,我意识到我无法一次动态检查和映射值。

所以,如果有人说这种方法我怎样才能一次正确地检查和发送值呢?

1 个答案:

答案 0 :(得分:0)

首先要注意的是,您的输入XML应该格式正确,这意味着它必须具有包含所有Characteristics元素的单个根元素。像这样:

<parent>
    <Characteristics>
        <Cname>elem_d</Cname>
        <Cvalue>123</Cvalue>
    </Characteristics>
    <Characteristics>
        <Cname>elem_a</Cname>
        <Cvalue>073</Cvalue>
    </Characteristics>
</parent>

但是要回答你的问题,你可以在这里使用xsl:element元素,它(与属性值模板一起)允许你动态指定一个元素。所以,你会写这样的东西

 <xsl:element name="{Cname}">

请注意花括号的使用,这意味着它被视为要计算以获取名称的表达式。 (即元素的名称将是你的XML中Cname元素的值)。如果你刚写了<xsl:element name="Cname" />,它就会创建一个元素<cname>

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" />

    <xsl:template match="Characteristics">
      <xsl:element name="{Cname}">
          <xsl:value-of select="Cvalue" />
      </xsl:element>
    </xsl:template>

    <xsl:template match="/*">
        <parent>
            <xsl:apply-templates />
        </parent>
    </xsl:template>
</xsl:stylesheet>

编辑:如果您希望对结果元素进行排序,则可以对xsl:sort使用xsl:apply-templates指令。试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" />

    <xsl:template match="Characteristics">
      <xsl:element name="{Cname}">
          <xsl:value-of select="Cvalue" />
      </xsl:element>
    </xsl:template>

    <xsl:template match="/*">
        <parent>
            <xsl:apply-templates select="Characteristics">
                <xsl:sort select="Cname" />
            </xsl:apply-templates>
        </parent>
    </xsl:template>
</xsl:stylesheet>

编辑2:如果“目标XML”是您实际想要使用Characteristics数据填充的实际文件,则另一种使用document函数访问目标XML的方法XSLT,简单地迭代子节点,用源XML中的数据填充它们。

尝试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" />

    <xsl:variable name="Characteristics" select="//Characteristics" />

    <xsl:template match="Parent/*">
      <xsl:copy>
          <xsl:value-of select="$Characteristics[Cname = local-name(current())]/Cvalue" />
      </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <Parent>
            <xsl:apply-templates select="document('Target.xml')/Parent/*" />
        </Parent>
    </xsl:template>
</xsl:stylesheet>