xmlstarlet 附加到 XML 中的节点
xmlstarlet append to a node in XML
我有一个包含以下条目的 xml 文件:
....
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.SynonymGraphFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
....
我想在 <analyzer type="index">
中注入以下 XML 节点:
<filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"/>
所以,最终的预期 XML 看起来像这样:
....
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.SynonymGraphFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
....
为此,我试过像这样使用 xmlstarlet:
xmlstarlet ed --inplace -s "//fieldType" -t elem -n "text_general" -i "//filter" -t attr -n "class" -v ""solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"" <file_name_here>
但显然,这不起作用(当我 运行 时,它真的弄乱了我的 XML 文件!)。我是 xmlstarlet 的新手,很难使用正确的语法来实现这个目标。我也认为在我的尝试中引用有问题。
您应该可以通过创建一个新的 filter
元素然后向其添加属性来完成此操作(新的 filter
现在是 [= 中的最后一个 filter
元素16=])...
xmlstarlet ed --inplace -s '//analyzer[@type="index"]' -t elem -n filter -i '//analyzer[@type="index"]/filter[last()]' -t attr -n class -v solr.NGramFilterFactory -i '//analyzer[@type="index"]/filter[last()]' -t attr -n minGramSize -v 1 -i '//analyzer[@type="index"]/filter[last()]' -t attr -n maxGramSize -v 20 input.xml
另一种选择是使用 XSLT。我认为这比尝试从命令行执行所有操作要容易得多...
xmlstarlet tr so.xsl input.xml > output.xml
XSLT 1.0 (so.xsl)
<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="analyzer[@type='index']">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我有一个包含以下条目的 xml 文件:
....
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.SynonymGraphFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
....
我想在 <analyzer type="index">
中注入以下 XML 节点:
<filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"/>
所以,最终的预期 XML 看起来像这样:
....
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.SynonymGraphFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
....
为此,我试过像这样使用 xmlstarlet:
xmlstarlet ed --inplace -s "//fieldType" -t elem -n "text_general" -i "//filter" -t attr -n "class" -v ""solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"" <file_name_here>
但显然,这不起作用(当我 运行 时,它真的弄乱了我的 XML 文件!)。我是 xmlstarlet 的新手,很难使用正确的语法来实现这个目标。我也认为在我的尝试中引用有问题。
您应该可以通过创建一个新的 filter
元素然后向其添加属性来完成此操作(新的 filter
现在是 [= 中的最后一个 filter
元素16=])...
xmlstarlet ed --inplace -s '//analyzer[@type="index"]' -t elem -n filter -i '//analyzer[@type="index"]/filter[last()]' -t attr -n class -v solr.NGramFilterFactory -i '//analyzer[@type="index"]/filter[last()]' -t attr -n minGramSize -v 1 -i '//analyzer[@type="index"]/filter[last()]' -t attr -n maxGramSize -v 20 input.xml
另一种选择是使用 XSLT。我认为这比尝试从命令行执行所有操作要容易得多...
xmlstarlet tr so.xsl input.xml > output.xml
XSLT 1.0 (so.xsl)
<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="analyzer[@type='index']">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>