我有一个包含以下条目的 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
中的最后一个 analyzer
元素)...
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>