身份模板特定元素,排除其他所有元素

时间:2015-12-22 11:19:19

标签: .net xml xslt xslt-1.0

使用以下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>

3 个答案:

答案 0 :(得分:1)

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

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

然后你就可以像往常一样编写模板,为Address或其子AddressLine做你想要或需要输出的内容。

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

所以要么尝试

<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>

在这两种情况下,我都不确定在生成的行方面你想要哪个确切的结果,因此可能需要对插入或添加换行符进行一些调整。

答案 1 :(得分:0)

无需添加显式模板优先级,只需使用匹配String strDetails = PropertyLoader.get("details"); String strDataKey1= PropertyLoader.get("datakey1"); String strDataKey2 = PropertyLoader.get("datakey2"); String strDetailsOrg = strDetails; strDetails = strDetails.replace(strDataKey1, "Programmatically Generated Value 1"); strDetailsOrg = strDetailsOrg.replace(strDataKey2, "Programmatically Generated Value 2"); 的模板和其他模板即可默认输出所有文本节点。

<强>样式表

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>

如果您希望输出不同,请说明应该更改的内容。

答案 2 :(得分:0)

一种简短的方法是“重新定义”内置模板规则,只复制选定的模板规则 - 在本例中为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>