XSL Modify на основе параметра командной строки

У меня есть следующий отрывок XML. Полный XML - это определение OVF.

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vmw="http://www.vmware.com/schema/ovf" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" x xml:lang="en-US">
      <Item>
        <rasd:Caption ovf:msgid="network.eth0.caption"/>
        <rasd:Connection>eth0</rasd:Connection>
        <rasd:Description ovf:msgid="network.eth0.description"/>
        <rasd:ElementName>eth0</rasd:ElementName>
        <rasd:InstanceID>13</rasd:InstanceID>
        <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
        <rasd:ResourceType>10</rasd:ResourceType>
      </Item>
      <Item>
        <rasd:Caption ovf:msgid="network.eth1.caption"/>
        <rasd:Connection>eth1</rasd:Connection>
        <rasd:Description ovf:msgid="network.eth1.description"/>
        <rasd:ElementName>eth1</rasd:ElementName>
        <rasd:InstanceID>14</rasd:InstanceID>
        <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
        <rasd:ResourceType>10</rasd:ResourceType>
      </Item>
      <Item>
        <rasd:Caption ovf:msgid="network.eth2.caption"/>
        <rasd:Connection>eth2</rasd:Connection>
        <rasd:Description ovf:msgid="network.eth2.description"/>
        <rasd:ElementName>eth2</rasd:ElementName>
        <rasd:InstanceID>15</rasd:InstanceID>
        <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
        <rasd:ResourceType>10</rasd:ResourceType>
      </Item>
      <Item>
        <rasd:Caption ovf:msgid="network.eth3.caption"/>
        <rasd:Connection>eth3</rasd:Connection>
        <rasd:Description ovf:msgid="network.eth3.description"/>
        <rasd:ElementName>eth3</rasd:ElementName>
        <rasd:InstanceID>16</rasd:InstanceID>
        <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
        <rasd:ResourceType>10</rasd:ResourceType>
      </Item>     
</Envelope>

Я пытаюсь вставить строку <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>перед <rasd:Connection>eth*</rasd:Connection> линия, но не на всех из них. Я получил следующий XSL, и он работает, но проблема в том, что мне приходится жестко кодировать каждый интерфейс, который я хочу отключить.

<xsl:template match="rasd:Connection[text()='eth0']">
    <xsl:if test="$disableEths='true'">
        <xsl:element name="rasd:AutomaticAllocation">false</xsl:element>
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template> 
<xsl:template match="rasd:Connection[text()='eth1']">
    <xsl:if test="$disableEths='true'">
        <xsl:element name="rasd:AutomaticAllocation">false</xsl:element>
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template> 
<xsl:template match="rasd:Connection[text()='eth2']">
    <xsl:if test="$disableEths='true'">
        <xsl:element name="rasd:AutomaticAllocation">false</xsl:element>
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template>

Есть ли способ, чтобы пользователь передал параметр, содержащий разделенный список значений, которые он хочет отключить, и, если параметр не введен, не отключите ни одно из них? Использование xsltproc в качестве процессора, если это имеет значение.

2 ответа

Решение

Как предлагается в комментариях, должен ли пользователь создать xml-файл, названный, например, DisableItems.xml, как показано ниже (который, кстати, может быть получен из файлов с текстовым разделителем, .txt, .csv, .tab и т. Д., С использованием общего назначения). языки: C#, Java, Perl, PHP, Python, R, VB...):

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <disableitem>eth1</disableitem>
  <disableitem>eth2</disableitem>
  <disableitem>eth3</disableitem>  
</root>

Затем XSLT может искать соответственно, используя его document() функция. Убедитесь, что другой XML-файл находится в том же каталоге, что и исходный XML-файл:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
               xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <!-- Identity Transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>  

  <xsl:template match="rasd:Connection[text()=document('DisableItems.xml')/root/disableitem]">
    <xsl:element name="rasd:AutomaticAllocation">false</xsl:element>
    <xsl:copy-of select="."/>
  </xsl:template>

</xsl:transform>

Вывод (обратите внимание, что eth0 не указан в справочнике xml, не имеет элемента false)

<?xml version='1.0' encoding='UTF-8'?>
<Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vmw="http://www.vmware.com/schema/ovf" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-US">
  <Item>
    <rasd:Caption ovf:msgid="network.eth0.caption"/>
    <rasd:Connection>eth0</rasd:Connection>
    <rasd:Description ovf:msgid="network.eth0.description"/>
    <rasd:ElementName>eth0</rasd:ElementName>
    <rasd:InstanceID>13</rasd:InstanceID>
    <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
    <rasd:ResourceType>10</rasd:ResourceType>
  </Item>
  <Item>
    <rasd:Caption ovf:msgid="network.eth1.caption"/>
    <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
    <rasd:Connection>eth1</rasd:Connection>
    <rasd:Description ovf:msgid="network.eth1.description"/>
    <rasd:ElementName>eth1</rasd:ElementName>
    <rasd:InstanceID>14</rasd:InstanceID>
    <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
    <rasd:ResourceType>10</rasd:ResourceType>
  </Item>
  <Item>
    <rasd:Caption ovf:msgid="network.eth2.caption"/>
    <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
    <rasd:Connection>eth2</rasd:Connection>
    <rasd:Description ovf:msgid="network.eth2.description"/>
    <rasd:ElementName>eth2</rasd:ElementName>
    <rasd:InstanceID>15</rasd:InstanceID>
    <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
    <rasd:ResourceType>10</rasd:ResourceType>
  </Item>
  <Item>
    <rasd:Caption ovf:msgid="network.eth3.caption"/>
    <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
    <rasd:Connection>eth3</rasd:Connection>
    <rasd:Description ovf:msgid="network.eth3.description"/>
    <rasd:ElementName>eth3</rasd:ElementName>
    <rasd:InstanceID>16</rasd:InstanceID>
    <rasd:ResourceSubType>VmxNet3</rasd:ResourceSubType>
    <rasd:ResourceType>10</rasd:ResourceType>
  </Item>
</Envelope>

Если вы проходите в --stringparam со строкой списка значений через запятую, тогда с помощью xsltproc вы можете использовать EXSLT str:tokenize функционировать следующим образом:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0"
  xmlns:str="http://exslt.org/strings"
  exclude-result-prefixes="str"
  xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">

<xsl:output indent="yes"/>

<xsl:param name="disableEths" select="'true'"/>
<xsl:param name="con-to-change" select="'eth0,eth1,eth2'"/>

<xsl:template match="@* | node()" name="identity"> 
  <xsl:copy> 
    <xsl:apply-templates select="@* | node()"/> 
  </xsl:copy> 
</xsl:template> 

<xsl:template match="rasd:Connection">
  <xsl:choose>
    <xsl:when test=". = str:tokenize($con-to-change, ',') and $disableEths='true'">
        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
        <xsl:copy-of select="."/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="identity"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template> 

</xsl:stylesheet>

Конечно, было бы желательно использовать параметр непосредственно в шаблоне сопоставления, но использование переменной или ссылки на параметр в шаблоне сопоставления не разрешено в XSLT 1.0, я думал, что xsltproc позволяет это, но в тесте, имеющем match="rasd:Connection[. = str:tokenize($con-to-change, ',')]" Я получил сообщение об ошибке о неопределенной переменной, поэтому все, что я могу предложить, - это приведенное выше, что перемещает проверку в шаблон.

Другие вопросы по тегам