【问题标题】:xslt Converting text nodes to attributesxslt 将文本节点转换为属性
【发布时间】:2015-12-06 20:34:40
【问题描述】:

我制作了一个 xslt 脚本,它将采用任何 xml 脚本并将元素中的文本节点转换为这些元素的属性。元素将只有子元素或文本节点,但不会有属性或其他任何东西,例如

 <example>
    <A>12</A>
     <B></B>
  <example>

最终应该看起来像:

  <example>
    <A Val='12'></A>
    <B></B>
  <example>

这是我的脚本,它基本上有两个 if,如果元素有一个文本节点,则创建一个具有相同名称的新元素,但如果它不只是复制元素,则将文本作为属性

<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:strip-space elements="*"/>
<xsl:template match="/">
         <xsl:for-each select="*">
                <xsl:when test="./text()"/>
                           <xsl:element name="{local-name()}" >
                        <xsl:attribute name="Val">
                              <xsl:value-of select="normalize- space(text())"/>
                         </xsl:attribute>
                    </xsl:element>
                    </xsl:when>
                    <xsl:otherwise>
                             <xsl:copy-of select="."/>
                   </xsl:otherwise>         
             </xsl:for-each>
    </xsl:template>

xml 将比我的示例更复杂。

【问题讨论】:

  • 您的实际 xml 是否有任何混合内容(包含文本和元素子元素的元素)?如果有,应该如何处理?
  • 是的,文本应该成为父级的属性
  • 所以&lt;a&gt;some a text &lt;b&gt;some b text&lt;/b&gt; more a text&lt;/a&gt; 变成&lt;a Val="some a text more a text"&gt;&lt;b Val="some b text"/&gt;&lt;/a&gt;" 或??

标签: xml xslt


【解决方案1】:

我不会使用xsl:for-each(拉式方法),而是使用推式方法...

XML 输入

<example>
    <A>12</A>
    <A>some a text <B>some b text</B> more a text</A>
    <B></B>
</example>

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:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[text()]">
    <xsl:variable name="text">
      <xsl:apply-templates select="text()"/>
    </xsl:variable>
    <xsl:copy>
      <xsl:attribute name="Val">
        <xsl:value-of select="normalize-space($text)"/>
      </xsl:attribute>
      <xsl:apply-templates select="@*|*"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

XML 输出

<example>
   <A Val="12"/>
   <A Val="some a text more a text">
      <B Val="some b text"/>
   </A>
   <B/>
</example>

【讨论】: