转换多个XML文件

时间:2014-04-25 04:18:25

标签: xml xslt

我有2个XML文件需要根据匹配转换为1。主文件(Assets.xml)看起来像这样

<Records>
  <Record>
    <Field id="15072">Server A</Field>
    <Field id="15073">
      <ListValues>
        <ListValue id="65502">Information</ListValue>
      </ListValues>
    </Field>
    <Field id="15083">
      <Reference id="205773">Control Instance A</Reference>
    </Field>
  </Record>
  <Record>
    <Field id="15072">Server B</Field>
    <Field id="15073">
      <ListValues>
        <ListValue id="65502">Physical</ListValue>
      </ListValues>
    </Field>
    <Field id="15083">
      <Reference id="205773">Control Instance A</Reference>
    </Field>
  </Record>
</Records>

第二个文件(ControlDefinitions.xml)看起来像这样

<Records>
  <Record>
    <Field id="15056">AR005</Field>
    <Field id="15086">
      <ListValues>
        <ListValue id="65504">Information</ListValue>
      </ListValues>
    </Field>
  </Record>
  <Record>
    <Field id="15056">AR001</Field>
    <Field id="15086">
      <ListValues>
        <ListValue id="65504">Information</ListValue>
      </ListValues>
    </Field>
  </Record>
  <Record>
    <Field id="15056">AR002</Field>
    <Field id="15086">
      <ListValues>
        <ListValue id="65504">Physical</ListValue>
      </ListValues>
    </Field>
  </Record>
</Records>

对于输出,我需要为具有相同类型(即信息,物理等)的每个资产/控制定义组合创建单个记录。输出看起来应该是这样的。

<InstanceRecords>
  <InstanceRecord>
    <Asset>Server A</Asset>
    <ControlInstance>Control Instance A</ControlInstance>
    <ControlDefinition>AR005</ControlDefinition>
  </InstanceRecord>
  <InstanceRecord>
    <Asset>Server A</Asset>
    <ControlInstance>Control Instance A</ControlInstance>
    <ControlDefinition>AR002</ControlDefinition>
  </InstanceRecord>
</InstanceRecords>

我一直使用的样式表如下。有没有办法做到这一点?任何帮助将不胜感激!谢谢!

<?xml version="1.0" encoding="utf-8"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:variable name="control_definitions" select="document('../XML/ControlDefinitions.xml')"/>

    <xsl:template name="getAsset">
      <xsl:value-of select="Field[@id='15072']"/>
    </xsl:template>

    <xsl:template name="getISMSInstance">
      <xsl:value-of select="Field[@id='15083']/Reference"/>
    </xsl:template>

    <xsl:template name="getControlDef">
      <xsl:for-each select="$control_definitions/Records/Record">
        <xsl:if test="Field[@id='15086']/ListValues/ListValue='Information'">
          <ControlDefinition>
            <xsl:value-of select="$control_definitions/Records/Record/Field[@id='15056']"/>
              </ControlDefinition>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="Records">
      <InstanceRecords>
        <xsl:for-each select="Record">
          <xsl:if test="Field[@id='15073']/ListValues/ListValue='Information'">
            <InstanceRecord>
              <Asset>
                <xsl:call-template name="getAsset"/>
              </Asset>
              <ControlInstance>
                <xsl:call-template name="getInstance"/>
              </ControlInstance>
              <xsl:call-template name="getControlDef"/>
            </InstanceRecord>
          </xsl:if>
        </xsl:for-each>
      </InstanceRecords>
    </xsl:template>
  </xsl:stylesheet>

谢谢!这对于匹配ListValues非常有用,但并不能完全满足所需的输出。下面是我想要生成的输出。那可能吗?谢谢!

<InstanceRecords>
  <InstanceRecord>
    <Asset>Server A</Asset>
    <ControlInstance>Control Instance A</ControlInstance>
    <ControlDefinition>AR005</ControlDefinition>
  </InstanceRecord>
  <InstanceRecord>
    <Asset>Server A</Asset>
    <ControlInstance>Control Instance A</ControlInstance>
    <ControlDefinition>AR001</ControlDefinition>
  </InstanceRecord>
  <InstanceRecord>
    <Asset>Server B</Asset>
    <ControlInstance>Control Instance A</ControlInstance>
    <ControlDefinition>AR002</ControlDefinition>
  </InstanceRecord>
</InstanceRecords>

1 个答案:

答案 0 :(得分:0)

在与记录匹配的模板中,而不是专门测试“信息”,您可以将实际的 ListValue 作为参数传递给您的命名模板

   <xsl:call-template name="getControlDef">
       <xsl:with-param name="type" select="Field[@id='15073']/ListValues/ListValue" />
   </xsl:call-template>

实际上,因为最终你想要为每条记录生成 InstanceRecord 元素,所以如果你将“资产”和“实例”值作为参数传递,它也会有所帮助

  <xsl:call-template name="getControlDef">
    <xsl:with-param name="instance"><xsl:call-template name="getInstance"/></xsl:with-param>
    <xsl:with-param name="asset"><xsl:call-template name="getAsset"/></xsl:with-param>
    <xsl:with-param name="type" select="Field[@id='15073']/ListValues/ListValue" />
   </xsl:call-template>

然后在 getControlDef 模板中,你会像这样测试它

<xsl:template name="getControlDef">
  <xsl:param name="type" />
  <xsl:for-each select="$control_definitions/Records/Record">
    <xsl:if test="Field[@id='15086']/ListValues/ListValue=$type">

或者,更好的是,将条件添加到 xsl:for-each

<xsl:template name="getControlDef">
  <xsl:param name="type" />
  <xsl:for-each select="$control_definitions/Records/Record[Field[@id='15086']/ListValues/ListValue=$type]">

在for-each循环中,您将输出 InstanceRecord ,就像这样......

    <InstanceRecord>
      <Asset>
        <xsl:value-of select="$asset" />
      </Asset>

......等等其他领域。

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />

    <xsl:variable name="control_definitions" select="document('../XML/ControlDefinitions.xml')"/>

    <xsl:template name="getAsset">
      <xsl:value-of select="Field[@id='15072']"/>
    </xsl:template>

    <xsl:template name="getInstance">
      <xsl:value-of select="Field[@id='15083']/Reference"/>
    </xsl:template>

    <xsl:template name="getControlDef">
      <xsl:param name="type" />
      <xsl:param name="asset" />
      <xsl:param name="instance" />
      <xsl:for-each select="$control_definitions/Records/Record[Field[@id='15086']/ListValues/ListValue=$type]">
        <InstanceRecord>
          <Asset>
            <xsl:value-of select="$asset" />
          </Asset>
          <ControlInstance>
            <xsl:value-of select="$instance" />
          </ControlInstance>
          <ControlDefinition>
            <xsl:value-of select="Field[@id='15056']"/>
          </ControlDefinition>
        </InstanceRecord>
      </xsl:for-each>
    </xsl:template>

    <xsl:template match="Records">
      <InstanceRecords>
        <xsl:for-each select="Record">
          <xsl:call-template name="getControlDef">
            <xsl:with-param name="instance"><xsl:call-template name="getInstance"/></xsl:with-param>
            <xsl:with-param name="asset"><xsl:call-template name="getAsset"/></xsl:with-param>
            <xsl:with-param name="type" select="Field[@id='15073']/ListValues/ListValue" />
          </xsl:call-template>
        </xsl:for-each>
      </InstanceRecords>
    </xsl:template>
</xsl:stylesheet>