2008-09-23 66 views
1

想象我有folling XML文件:<b>中间/ B >后移动XML节点的子节点向上

<一个>前< </A >

我想把它转换成弄成这个样子:

<一个> beforemiddleafter </A >

换句话说,我想要获取某个节点的所有子节点,并将它们按顺序移动到父节点。这就像执行这个命令:“mv ./directory/*。”,但对于xml节点。

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

回声 “<一个>前<b>中间</B > <后/ A >” | xmlstarlet ed -m“// b/*”“..”

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

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

回答

2

如果您的实际目标是从网页上删除的链接,那么你应该使用这样一个样式表,它与所有的XHTML相匹配个元素(我假设你使用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> 

该样式会处理,你有什么嵌套所需的<a>元素的情况保留,如:

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

,你会想出来的:

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

它会处理,你必须嵌套在通常的父母(在<p>元件)和<a>元素之间的意想不到的元素中的链接的情况,如:

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

这正是我正在寻找的。 感谢您的详细解答,解释它是如何工作的 – Rory 2008-09-25 13:14:22

2

在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一无所知,所以也许别人可以填空,例如。某种可以执行上述操作的命令行调用。

3

实施例输入文件(的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:使用

xml tr collapse.xsl test.xml 

与XmlStarlet

<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> 

运行产地:

<?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文档)。第二个模板特别匹配您想要“折叠”的元素,并仅复制标签并插入元素的字符串值(=后代节点的字符串值的连接)。

0

你试过吗?

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> 
1

使用xmlstarlet:

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