【问题标题】:XSLT Add nested element to the last node based on the existing elementXSLT 根据现有元素将嵌套元素添加到最后一个节点
【发布时间】:2013-07-24 15:25:33
【问题描述】:

我有以下 XML,该 XML 中有多次出现的“item”元素,并且会有单次出现的“info”元素

<?xml version="1.0" encoding="utf-8" ?>

<root xmlns="http://temo.com/tempe.xsd">


<di>    
<md>2013-07-09T09:43:00</md>
</di>


<list>

<item>
<Name>test</Name>
<section block1="true">
<block1>
<move>1</move>
<info>
<item1>test item 1</item1>
<item2>false</item2>
<item3>1</item3>
</info>
</block1>
<block2>
...
</block2>
</section>
</item>
</list>

<option>
...
</option>

</root>

我想将其转换为以下格式,即,如果存在“移动”元素,则应在“信息”元素的最后位置添加新元素

<item4>
 <item5>1</item5>
</item4>


<?xml version="1.0" encoding="utf-8" ?>

<root xmlns="http://temo.com/tempe.xsd">


<di>    
<md>2013-07-09T09:43:00</md>
</di>


<list>

<item>
<Name>test</Name>
<section block1="true">
<block1>
<move>1</move>
<info>
  <item1>test item 1</item1>
  <item2>false</item2>
  <item3>1</item3>
  <item4>
    <item5>1</item5>
  </item4>
</info>
</block1>
  <block2>
    ...
  </block2>
</section>
</item>
<item>
    ...
</item>
</list>
<option>
...
</option>

</root>

我正在使用下面的 XSLT 来转换成上面的格式

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes" encoding="utf-8"/>

<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="/info/*[position()=last()]">
<xsl:copy>
<xsl:choose>
<xsl:when test="/section/block/move">
<!--Add new element item4-->
<xsl:element name="item4">
<xsl:element name="item5">
<xsl:value-of select="section/block/move"/>
</xsl:element>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="identity" />
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

您能帮我找出 XSLT 中的问题吗? 我是 XSLT 的新手

谢谢你:)

【问题讨论】:

    标签: xslt xslt-1.0


    【解决方案1】:

    您在输入 XML 上有一个默认命名空间声明,输出 XML 也需要该命名空间来插入元素,所以您需要

    xmlns:tp="http://temo.com/tempe.xsd"

    在您的 xsl:stylesheet 根元素上,您需要调整路径和模式以使用该前缀,例如而不是info 你需要tp:info 而不是section/block/move 你需要tp:section/tp:block/tp:move 等等。

    XSLT 示例中的路径似乎错误,但是您使用了/section/block/move,但您的根元素是root,因此/section 永远不会选择任何内容,即使您添加了命名空间前缀。你的路径有block,输入有block1

    我没有尝试修复您的代码,而是编写了一个新样式表,它是

    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns="http://temo.com/tempe.xsd"
      xmlns:tp="http://temo.com/tempe.xsd"
      exclude-result-prefixes="tp"
      version="1.0">
    
    <xsl:param name="to-insert" xml:space="preserve">
    <item4>
     <item5><xsl:value-of select="//tp:section/tp:block1/tp:move"/></item5>
    </item4>
    </xsl:param>
    
    <xsl:template match="@* | node()">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:template>
    
    <xsl:template match="tp:item[.//tp:move[. = 1]]//tp:info">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
        <xsl:copy-of select="$to-insert"/>
      </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    

    输出

    <root xmlns="http://temo.com/tempe.xsd">
    
    
    <di>
    <md>2013-07-09T09:43:00</md>
    </di>
    
    
    <list>
    
    <item>
    <Name>test</Name>
    <section block1="true">
    <block1>
    <move>1</move>
    <info>
    <item1>test item 1</item1>
    <item2>false</item2>
    <item3>1</item3>
    
    <item4 xmlns:tp="http://temo.com/tempe.xsd">
     <item5>1</item5>
    </item4>
    </info>
    </block1>
    <block2>
    ...
    </block2>
    </section>
    </item>
    </list>
    
    <option>
    ...
    </option>
    
    </root>
    

    【讨论】:

    • 非常感谢!太棒了:)
    • 我有一个问题,我已将模板匹配更改为“pc:Signal[.//pc:StationSetReference[.=number()]]//pc:Data”,因为“move”元素可以有任何数值。参数 - $to-insert 总是返回移动元素的第一个匹配值。是否可以获得当前的“移动”元素值。
    • 是的,而不是 &lt;xsl:copy-of select="$to-insert"/&gt; 直接将元素放在那里,例如&lt;item4&gt;&lt;item5&gt;&lt;xsl:value-of select="../tp:move"/&gt;&lt;/item5&gt;&lt;/item4&gt;.
    • 谢谢你的想法,我试过 parent::pc:info/pc:move/node() 它给出了当前值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多