标识模板特定的元素,排除所有其他元素



使用下面的XML,如何仅将地址详细信息提取为CSV格式?

我认为我需要一个基于Identity模板的样式表,尽管我发现的示例很简单,并在列表中列出了要排除的元素。有没有一种简单的方法可以排除除Address和AddressLine之外的所有内容?

我正在使用.NET处理XLST转换。到目前为止,我提出的样式表没有返回任何内容。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="utf-8" />
  <xsl:strip-space elements="*"/>
  <xsl:param name="delim" select="','" />
  <xsl:param name="quote" select="'&quot;'" />
  <xsl:param name="break" select="'&#xa;'" />
  <xsl:template match="node()| @*">
    <xsl:copy>
      <xsl:apply-templates select="node()| @*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="AddressLine" priority="9">
    <xsl:value-of select="concat($quote, ., $quote, $delim)"/>
  </xsl:template>
  <xsl:template match="*" priority="0" />
</xsl:stylesheet>
<Sample Version="6" Date="2012-05-11">
  <Header>
    <CreatedDate>2015-12-02</CreatedDate>
    <CreatedTime>10:31:42</CreatedTime>
  </Header>
  <Message Group="1" Type="1" Protocol="1">
    <MessageHeader>
      <MessageReferenceNumber>1</MessageReferenceNumber>
    </MessageHeader>
    <TransactionHeader>
      <ReportPeriodStartDate>2002-04-01</ReportPeriodStartDate>
      <ReportPeriodEndDate>2015-11-30</ReportPeriodEndDate>
    </TransactionHeader>
    <Episode>
      <Person>
        <General>
          <Verified Status="02">
            <Identifier>001</Identifier>
            <PersonName>
              <Name>
                <FirstName>Foo</FirstName>
                <Surname>Bar</Surname>
              </Name>
            </PersonName>
            <Address>
              <AddressLine></AddressLine>
              <AddressLine>Street</AddressLine>
              <AddressLine>Town</AddressLine>
              <AddressLine>City</AddressLine>
            </Address>
          </Verified>
        </General>
      </Person>
      <Session>
        <Input>
          <StartDate>2015-10-31</StartDate>
          <StartTime>17:15:00</StartTime>
        </Input>
        <Output>
          <StatusCode>8</StatusCode>
          <LocationCode>9</LocationCode>
        </Output>
      </Session>
    </Episode>
    <MessageTrailer>
      <MessageReferenceNumber>1</MessageReferenceNumber>
    </MessageTrailer>
  </Message>
  <Message Group="1" Type="1" Protocol="1">
    <MessageHeader>
      <MessageReferenceNumber>2</MessageReferenceNumber>
    </MessageHeader>
    <TransactionHeader>
      <ReportPeriodStartDate>2002-04-01</ReportPeriodStartDate>
      <ReportPeriodEndDate>2015-11-30</ReportPeriodEndDate>
    </TransactionHeader>
    <Episode>
      <Person>
        <General>
          <Verified Status="02">
            <Identifier>002</Identifier>
            <PersonName>
              <Name>
                <FirstName>Foo</FirstName>
                <Surname>Bar</Surname>
              </Name>
            </PersonName>
            <Address>
              <AddressLine></AddressLine>
              <AddressLine>Street</AddressLine>
              <AddressLine>Town</AddressLine>
              <AddressLine>City</AddressLine>
            </Address>
          </Verified>
        </General>
      </Person>
      <Session>
        <Input>
          <StartDate>2015-10-31</StartDate>
          <StartTime>17:15:00</StartTime>
        </Input>
        <Output>
          <StatusCode>8</StatusCode>
          <LocationCode>9</LocationCode>
        </Output>
      </Session>
    </Episode>
    <MessageTrailer>
      <MessageReferenceNumber>2</MessageReferenceNumber>
    </MessageTrailer>
  </Message>
  <Trailer>
    <RecordCount>2</RecordCount>
  </Trailer>
</Sample>

如果你想创建纯文本,我认为身份转换模板没有意义,你只需要一个根节点的模板

<xsl:template match="/">
  <xsl:apply-templates select="//Address"/>
</xsl:template>

然后,您可以编写模板,为Address或其子级AddressLine执行您想要或需要输出的操作。

作为替代方案,您可以利用现有的默认模板来递归处理子节点,只需要确保覆盖text()节点的模板,否则所有元素的所有文本都将被输出。

所以要么试试

<xsl:template match="/">
  <xsl:apply-templates select="//Address"/>
</xsl:template>
  <xsl:template match="AddressLine">
    <xsl:value-of select="concat($quote, ., $quote, $delim)"/>
  </xsl:template>

或者仅仅是像这样的方法

<xsl:template match="*[not(self::Address)]/text()"/>
<xsl:template match="AddressLine">
  <xsl:value-of select="concat($quote, ., $quote, $delim)"/>
</xsl:template>

在这两种情况下,我都不确定您想要的生产线的确切结果,因此可能需要进行一些调整来插入或添加换行符。

一个简单的方法是"重新定义"内置模板规则,只复制选定的模板规则-在本例中为Address和子节点:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="*|@*">
    <xsl:apply-templates select="*" />
  </xsl:template>
  <xsl:template match="Address">
    <xsl:copy-of select="." />
  </xsl:template>
</xsl:stylesheet>

导致

<?xml version="1.0"?>
<Address>
    <AddressLine/>
    <AddressLine>Street</AddressLine>
    <AddressLine>Town</AddressLine>
    <AddressLine>City</AddressLine>
</Address>
<Address>
    <AddressLine/>
    <AddressLine>Street</AddressLine>
    <AddressLine>Town</AddressLine>
    <AddressLine>City</AddressLine>
</Address>

无需添加明确的模板优先级,只需使用一个匹配AddressLine的模板和另一个模板,即可在默认情况下防止输出所有文本节点。

样式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="utf-8" />
  <xsl:strip-space elements="*"/>
  <xsl:param name="delim" select="','" />
  <xsl:param name="quote" select="'&quot;'" />
  <xsl:param name="break" select="'&#xa;'" />

  <xsl:template match="AddressLine">
    <xsl:value-of select="concat($quote, ., $quote, $delim)"/>
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

文本输出

"","Street","Town","City","","Street","Town","City",

如果您希望输出有所不同,请解释应该更改的内容。

相关内容

  • 没有找到相关文章

最新更新