【问题标题】:Moving the child nodes of an XML node upwards向上移动 XML 节点的子节点
【发布时间】:2010-09-12 13:17:15
【问题描述】:

假设我有以下 XML 文件:

之前中间之后

我想把它转换成这样的:

前中后

也就是说我想获取某个节点的所有子节点,并按顺序移动到父节点。这就像执行以下命令:“mv ./directory/* .”,但用于 xml 节点。

我想在使用 unix 命令行工具时做到这一点。我一直在尝试使用 xmlstarlet,它是一个强大的命令行 XML 操纵器。我试过做这样的事情,但它不起作用

echo "之前中间之后" | xmlstarlet ed -m "//b/*" ".."

更新:XSLT 模板很好,因为它们可以从命令行调用。

我的目标是“从 XHTML 页面中删除链接”,换句话说,用链接标记的内容替换链接所在的位置。

【问题讨论】:

    标签: xml xslt command-line-interface


    【解决方案1】:

    使用 xmlstarlet:

    xmlstr='<a>before<b>middle</b>after</a>'
    updatestr="$(echo "$xmlstr" | xmlstarlet sel -T -t -m "/a/b" -v '../.' -n | sed -n '1{p;q;}')"
    echo "$xmlstr" | xmlstarlet ed -u "/a" -v "$updatestr"
    

    【讨论】:

      【解决方案2】:

      如果您的实际目标是从网页中删除链接,那么您应该使用这样的样式表,它匹配所有 XHTML &lt;a&gt; 元素(我假设您使用的是 XHTML?)并简单地应用模板到他们的内容:

      <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:h="http://www.w3.org/1999/xhtml"
        exclude-result-prefixes="h">
      
      <!-- Don't copy the <a> elements, just process their content -->
      <xsl:template match="h:a">
        <xsl:apply-templates />
      </xsl:template>
      
      <!-- identity template; copies everything by default -->
      <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
      </xsl:template>
      
      </xsl:stylesheet>
      

      此样式表将处理您想要保留的&lt;a&gt; 元素中嵌套了一些内容 的情况,例如:

      <p>Here is <a href="....">some <em>linked</em> text</a>.</p>
      

      你想出来的样子:

      <p>Here is some <em>linked</em> text.</p>
      

      它将处理链接嵌套在通常父元素(&lt;p&gt; 元素)和 &lt;a&gt; 元素之间的意外元素中的情况,例如:

      <p>Here is <em>some <a href="...">linked</a> text</em>.</p>
      

      【讨论】:

      • 这正是我想要的。感谢您提供详细的答案,解释它是如何工作的
      【解决方案3】:

      你试过了吗?

      file.xml

      <r>
          <a>start<b>middle</b>end</a>
      </r>
      

      template.xsl

      <xsl:template match="/">
          <a><xsl:value-of select="r/a" /></a>
      </xsl:template>
      

      output

      <a>startmiddleend</a>
      

      【讨论】:

        【解决方案4】:

        示例输入文件(test.xml):

        <?xml version="1.0" encoding="UTF-8"?>
        <test>
        <x>before<y>middle</y>after</x>
        <a>before<b>middle</b>after</a>
        <a>before<b>middle</b>after</a>
        <x>before<y>middle</y>after</x>
        <a>before<b>middle</b>after</a>
        <embedded>foo<a>before<b>middle</b>after</a>bar</embedded>
        </test>
        

        XSLT 样式表(collapse.xsl:

            <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        
              <xsl:template match="@*|node()">
                <xsl:copy>
                  <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
              </xsl:template>
        
              <xsl:template match="a">
                <xsl:copy>
                  <xsl:value-of select="."/>
                </xsl:copy>
              </xsl:template>
        
            </xsl:stylesheet>
        

        使用 XmlStarlet 运行

        xml tr collapse.xsl test.xml
        

        生产:

        <?xml version="1.0"?>
        <test>
        <x>before<y>middle</y>after</x>
        <a>beforemiddleafter</a>
        <a>beforemiddleafter</a>
        <x>before<y>middle</y>after</x>
        <a>beforemiddleafter</a>
        <embedded>foo<a>beforemiddleafter</a>bar</embedded>
        </test>
        

        样式表中的第一个模板是基本的身份转换(只需复制整个输入 XML 文档)。第二个模板专门匹配您要“折叠”的元素,并仅复制标签并插入元素的字符串值(=后代节点的字符串值的串联)。

        【讨论】:

          【解决方案5】:

          在 XSLT 中,您可以只写:

          <xsl:template match="a"><a><xsl:apply-templates /></a></xsl:template>
          
          <xsl:template match="a/b"><xsl:value-of select="."/></xsl:template>
          

          你会得到:

          <a>beforemiddleafter</a>
          

          因此,如果您想以简单的方式执行此操作,您可以创建一个 XSL 样式表并通过它运行您的 XML 文件。

          但是,我意识到这不是您所说的(使用 Unix 命令行)。我对Unix一无所知,所以也许其他人可以填补空白,例如。某种可以执行上述操作的命令行调用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-02-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多