xmlstarlet добавить к узлу в XML - PullRequest
       13

xmlstarlet добавить к узлу в XML

1 голос
/ 20 января 2020

У меня есть файл 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>
 ....

Я хотел бы добавить следующий узел XML в <analyzer type="index">:

<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 и испытываю трудности с правильным синтаксисом для достижения этой цели. Я также думаю, что в моей попытке есть проблема с цитированием.

1 Ответ

1 голос
/ 20 января 2020

Вы можете сделать это, создав новый элемент 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>
...