基于命令行参数的 XSL 修改
XSL Modify Based on Command Line Param
我有以下 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:Connection>eth*</rasd:Connection>
行之前插入 <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
行,但不是在所有行上。到目前为止,我已经获得了以下 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 作为处理器。
如果您传入的 --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, ',')]"
我收到了一些关于未定义变量的错误消息,所以我只能建议将检查移动到模板中。
如评论中所建议,用户是否应该生成一个 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>
我有以下 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:Connection>eth*</rasd:Connection>
行之前插入 <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
行,但不是在所有行上。到目前为止,我已经获得了以下 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 作为处理器。
如果您传入的 --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, ',')]"
我收到了一些关于未定义变量的错误消息,所以我只能建议将检查移动到模板中。
如评论中所建议,用户是否应该生成一个 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>