XSLT用于获取所需的行并同时更改节点值

时间:2012-07-30 23:33:03

标签: xml xslt

我的当前XML如下:

<?xml version="1.0" encoding="utf-8"?>
<Rowsets DateCreated="2012-07-17T11:57:07" EndDate="2012-07-17T11:57:07" StartDate="2012-07-17T10:57:07" Version="12.0.12 Build(9)">
    <Rowset>
        <Row>
            <CategoryID>1</CategoryID>
            <Name>Philip</Name>
            <City>London</City>
            <Phone>123</Phone>
        </Row>
        <Row>
            <CategoryID>2</CategoryID>
            <Name>Derek</Name>
            <City>Seattle</City>
            <Phone>500</Phone>
        </Row>
        <Row>
            <CategoryID>3</CategoryID>
            <Name>Bruke</Name>
            <City>LosAngeles</City>
            <Phone>600</Phone>
        </Row>
        <Row>
            <CategoryID>2</CategoryID>
            <Name>Yang</Name>
            <City>SFO</City>
            <Phone>1233</Phone>
        </Row>
        <Row>
            <CategoryID>3</CategoryID>
            <Name>Cristina</Name>
            <City>SanJose</City>
            <Phone>890</Phone>
        </Row>
        <Row>
            <CategoryID>4</CategoryID>
            <Name>Meredith</Name>
            <City>Sunnyvale</City>
            <Phone>788</Phone>
        </Row>
        <Row>
            <CategoryID>4</CategoryID>
            <Name>Grey</Name>
            <City>MountainView</City>
            <Phone>456</Phone>
        </Row>
        <Row>
            <CategoryID>5</CategoryID>
            <Name>Torrence</Name>
            <City>SAntaClara</City>
            <Phone>432</Phone>
        </Row>
    </Rowset>
</Rowsets>

现在我只想要那些<Row>为2的<CategoryID>。所以我的XSLT正在关注:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:java="http://xml.apache.org/xslt/java" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="java" version="1.0">
    <xsl:output media-type="text/xml" method="xml"/>
    <!-- Filters refdoc based on condition and  data  -->
    <xsl:template match="/">
        <Rowsets>
            <xsl:for-each select="/Rowsets/Rowset">
                <Rowset>
                    <xsl:copy-of select="Columns"/>
                    <xsl:for-each select="Row[CategoryID = '2']">
                        <xsl:copy-of select="."/>
                    </xsl:for-each>
                </Rowset>
            </xsl:for-each>
        </Rowsets>
    </xsl:template>
</xsl:stylesheet>

这个XSLT给了我以下XML:

<?xml version="1.0" encoding="utf-8"?>
<Rowsets>
    <Rowset>
        <Row>
            <CategoryID>2</CategoryID>
            <Name>Derek</Name>
            <City>Seattle</City>
            <Phone>500</Phone>
        </Row>
        <Row>
            <CategoryID>2</CategoryID>
            <Name>Yang</Name>
            <City>SFO</City>
            <Phone>1233</Phone>
        </Row>
    </Rowset>
</Rowsets>

但现在我的要求是,在上面新的转换XML中,我还想将CategoryID更改为1.

所以我的最终XML应该是这样的:

<?xml version="1.0" encoding="utf-8"?>
<Rowsets>
    <Rowset>
        <Row>
            <CategoryID>1</CategoryID>
            <Name>Derek</Name>
            <City>Seattle</City>
            <Phone>500</Phone>
        </Row>
        <Row>
            <CategoryID>1</CategoryID>
            <Name>Yang</Name>
            <City>SFO</City>
            <Phone>1233</Phone>
        </Row>
    </Rowset>
</Rowsets>

我不确定如何使用相同的XSLT以最佳方式实现这一目标。任何人都可以帮我吗?

2 个答案:

答案 0 :(得分:2)

此转化

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="Row[not(CategoryID = 2)]"/>

 <xsl:template match="CategoryID/text()">1</xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<Rowsets DateCreated="2012-07-17T11:57:07" EndDate="2012-07-17T11:57:07" StartDate="2012-07-17T10:57:07" Version="12.0.12 Build(9)">
    <Rowset>
        <Row>
            <CategoryID>1</CategoryID>
            <Name>Philip</Name>
            <City>London</City>
            <Phone>123</Phone>
        </Row>
        <Row>
            <CategoryID>2</CategoryID>
            <Name>Derek</Name>
            <City>Seattle</City>
            <Phone>500</Phone>
        </Row>
        <Row>
            <CategoryID>3</CategoryID>
            <Name>Bruke</Name>
            <City>LosAngeles</City>
            <Phone>600</Phone>
        </Row>
        <Row>
            <CategoryID>2</CategoryID>
            <Name>Yang</Name>
            <City>SFO</City>
            <Phone>1233</Phone>
        </Row>
        <Row>
            <CategoryID>3</CategoryID>
            <Name>Cristina</Name>
            <City>SanJose</City>
            <Phone>890</Phone>
        </Row>
        <Row>
            <CategoryID>4</CategoryID>
            <Name>Meredith</Name>
            <City>Sunnyvale</City>
            <Phone>788</Phone>
        </Row>
        <Row>
            <CategoryID>4</CategoryID>
            <Name>Grey</Name>
            <City>MountainView</City>
            <Phone>456</Phone>
        </Row>
        <Row>
            <CategoryID>5</CategoryID>
            <Name>Torrence</Name>
            <City>SAntaClara</City>
            <Phone>432</Phone>
        </Row>
    </Rowset>
</Rowsets>

会产生想要的正确结果:

<Rowsets DateCreated="2012-07-17T11:57:07" EndDate="2012-07-17T11:57:07" StartDate="2012-07-17T10:57:07" Version="12.0.12 Build(9)">
   <Rowset>
      <Row>
         <CategoryID>1</CategoryID>
         <Name>Derek</Name>
         <City>Seattle</City>
         <Phone>500</Phone>
      </Row>
      <Row>
         <CategoryID>1</CategoryID>
         <Name>Yang</Name>
         <City>SFO</City>
         <Phone>1233</Phone>
      </Row>
   </Rowset>
</Rowsets>

<强>解释

  1. 正确使用和覆盖 identity rule

  2. 正确使用模板和模式匹配。

答案 1 :(得分:0)

我不确定这是否是最好的方法,但这应该有用。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:java="http://xml.apache.org/xslt/java" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="java" version="1.0">
  <xsl:output media-type="text/xml" method="xml"/>
  <!-- Filters refdoc based on condition and  data  -->
  <xsl:template match="/">
    <Rowsets>
      <xsl:for-each select="/Rowsets/Rowset">
        <Rowset>
          <xsl:copy-of select="Columns"/>
          <xsl:for-each select="Row[CategoryID = '2']">
            <Row>
              <xsl:apply-templates select="*" mode="Row" />
            </Row>
          </xsl:for-each>
        </Rowset>
      </xsl:for-each>
    </Rowsets>
  </xsl:template>

  <xsl:template match="*" mode="Row">
    <xsl:choose>
      <xsl:when test="current()[name()='CategoryID']">
        <xsl:copy>
          <xsl:text>1</xsl:text>
        </xsl:copy>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="." />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

输出为

<?xml version="1.0" encoding="UTF-8"?>
<Rowsets>
  <Rowset>
    <Row>
      <CategoryID>1</CategoryID>
      <Name>Derek</Name>
      <City>Seattle</City>
      <Phone>500</Phone>
    </Row>
    <Row>
      <CategoryID>1</CategoryID>
      <Name>Yang</Name>
      <City>SFO</City>
      <Phone>1233</Phone>
    </Row>
  </Rowset>
</Rowsets>