希望从以下XML内容中提取元素:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:inputText id="id"/>
...
</ui:composition>
可以使用以下方式选择所有h:inputText
元素:
xmlstarlet sel -t -c "//h:inputText" filename.xml
这会产生以下名称空间感染的输出:
<h:inputText
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets" id="id"/>
如何从输出中抑制名称空间?
使用正则表达式进行后期处理;但是:
通过xmllint或xmlstarlet传递第二遍,但这需要格式良好的XML文档。
使用xmllint会产生一组自己的命名空间问题。
制作仅包含ui:composition
和h:inputText
元素的文档:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:inputText id="id"/>
<h:inputText id="id"/>
</ui:composition>
这很棘手,因为h:inputText
元素可以出现在文档的任何深度。
答案 0 :(得分:1)
您可以使用XSLT。如果您希望按原样输出h:inputText
,则无法取消将前缀h:
绑定到uri http://java.sun.com/jsf/html
的名称空间声明。
创建input.xsl
:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://java.sun.com/jsf/html">
<xsl:output omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="//h:inputText"/>
</xsl:template>
<xsl:template match="h:inputText">
<xsl:copy>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
xmlstarlet tr input.xsl filename.xml
<h:inputText xmlns:h="http://java.sun.com/jsf/html" id="id"/>
您可以在没有命名空间的情况下输出inputText
,但是......
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://java.sun.com/jsf/html" exclude-result-prefixes="h">
<xsl:output omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="//h:inputText"/>
</xsl:template>
<xsl:template match="h:inputText">
<inputText>
<xsl:copy-of select="@*"/>
</inputText>
</xsl:template>
</xsl:stylesheet>
使用上面的命令行:
<inputText id="id"/>
注意:您可能需要在<xsl:text>
</xsl:text>
(或第二个示例中为</xsl:copy>
)之后添加</inputText>
以明确添加换行符。否则xmlstartlet可能会输出一行上的所有元素。 (我在indent="yes"
上使用xmlstarlet 1.6.1和xsl:output
并没有帮助我。)
由于涉及JSF,请考虑:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
exclude-result-prefixes="h f c ui a4j">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<h:html>
<xsl:apply-templates select="//h:inputText"/>
</h:html>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="h:inputText">
<xsl:text>
</xsl:text>
<h:inputText>
<xsl:copy-of select="@*"/>
</h:inputText>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
一个 XSLT-stylesheet 解决方案已经发布了一段时间,但是通过
我最近在 xmlstarlet 1.6.1 版上进行的实验
产生所需输出的命令行同上
<inputText id="id"/>
,
xmlstarlet sel -N = -t -m '//h:inputText' -e '{local-name()}' -c '@*' -b -n file.xml
其中 -N =
似乎将空前缀绑定到空命名空间。
如果您将 <f:inputText id="id"/><ui:inputText id="id"/>
添加到
输入文件并将上面命令中的 -m
子句更改为
-m '//f:inputText | //h:inputText | //ui:inputText'
它产生
每个匹配节点所需的输出。这将是一个回旋处,
和详细的,在 exclude-result-prefixes="f h ui"
上做的方式
命令行。
不出所料,user's guide 没有提到 -N
的这种用法,源代码的 parseNSArr(…)
也没有提供任何线索。
也许是有意为之——他们怎么会没有注意到呢? - 也许不是:
-N =
语法看起来有些可疑。但我肯定
远离 sed -e 's/ xmlns.*=".*"//g'
中列出的方法
user's guide。
答案 2 :(得分:0)
sed 没有非贪婪匹配
这还是太贪心了吗?
sed -e 's/ xmlns[^=]*="[^"]*"//g'