xmlstarlet 追加到 XML 中的节点

问题描述 投票:0回答:1

我有一个包含以下条目的 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 很陌生,并且很难使用正确的语法来实现此目标。我也认为我的尝试中引用有问题。

xml xmlstarlet
1个回答
2
投票

您应该能够通过创建一个新的

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>
© www.soinside.com 2019 - 2024. All rights reserved.