XSLT:for-each响应?

时间:2013-06-06 14:29:16

标签: xml xslt foreach plist

我正在将plist转换为XML,我很困惑为什么我的for-each会返回两个回复,而如果我将for-each更改为value-of,我完全没有回报。其他一切都有效,我只想从我的XSLT中获取单Description / Title / Username

XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

  <dict>

    <key>Playlists</key>
    <array>
      <dict>
        <key>All Items</key>
        <true/>
        <key>Playlist Items</key>
        <array>
          <dict>
            <key>Track ID</key>
            <integer>0</integer>
          </dict>
          <dict>
            <key>Track ID</key>
            <integer>1</integer>
          </dict>
          <dict>
            <key>Track ID</key>
            <integer>2</integer>
          </dict>
        </array>
        <key>Playlist Persistent ID</key>
        <string>pID505050</string>
      </dict>
    </array>

    <key>Tracks</key>
    <dict>

      <key>0</key>
      <dict>
        <key>Album</key>
        <string>Funeral</string>
        <key>Artist</key>
        <string>The Arcade Fire</string>
        <key>Name</key>
        <string>Neighborhood #3 (Power Out)</string>
        <key>Track ID</key>
        <string>0</string>
      </dict>

      <key>1</key>
      <dict>
        <key>Album</key>
        <string>Untrue</string>
        <key>Artist</key>
        <string>Burial</string>
        <key>Name</key>
        <string>Archangel</string>
        <key>Track ID</key>
        <string>1</string>
      </dict>

    </dict>

    <key>Upload Information</key>
    <dict>
      <key>Playlist Description</key>
      <string>My description</string>
      <key>Playlist Title</key>
      <string>Mytitle</string>
      <key>Username</key>
      <string>Maven</string>
    </dict>

  </dict>

</plist>

XSLT:

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

  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="/">
    <playlist>

      <xsl:for-each select="/*/*/dict[1]/dict">
        <xsl:element name="Artist">
          <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Artist']" />
        </xsl:element>
        <xsl:element name="Album">
          <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Album']" />
        </xsl:element>
        <xsl:element name="TrackID">
          <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Track ID']" />
        </xsl:element>
      </xsl:for-each>

      <xsl:for-each select="/*/*/dict">
        <xsl:element name="Description">
          <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Playlist Description']" />
        </xsl:element>
        <xsl:element name="Title">
          <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Playlist Title']" />
        </xsl:element>
        <xsl:element name="Username">
          <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Username']" />
        </xsl:element>

      </xsl:for-each>

    </playlist>

  </xsl:template>   

</xsl:stylesheet>

当前XSL输出:

<?xml version="1.0" encoding="UTF-8"?>
<playlist>
  <Artist>The Arcade Fire</Artist>
  <Album>Funeral</Album>
  <TrackID>0</TrackID>
  <Artist>Burial</Artist>
  <Album>Untrue</Album>
  <TrackID>1</TrackID>
  <Description></Description>
  <Title></Title>
  <Username></Username>
  <Description>My description</Description>
  <Title>Mytitle</Title>
  <Username>Maven</Username>
</playlist>

提前致谢!

2 个答案:

答案 0 :(得分:2)

我假设了一些事情,因为你的问题不太清楚:

  • 示例XML和XSLT格式不正确,因此我关闭了根元素
  • 您想要一个所有曲目的列表,而不仅仅是第一个,然后是播放列表上传信息
  • 我冒昧地将每个轨道包装在输出XML中的一个元素中。

然后我让你的每个XPath选择更明确:

<xsl:for-each select="//dict[preceding-sibling::*[1]='Tracks']/dict">

<xsl:for-each select="//dict[preceding-sibling::*[1]='Upload Information']">

同样,我清理了XPath的值,例如:

<xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Artist']" />

注意使用local-name()来检查第一个previous-sibling节点是否实际上被称为“key”。您的输入数据不是很好的XML:)

最后,我清理元素创建等。这是XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
    <playlist>
        <xsl:for-each select="//dict[preceding-sibling::*[1]='Tracks']/dict">
            <Track>
                <Artist>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Artist']" />
                </Artist>
                <Album>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Album']" />
                </Album>
                <TrackID>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Track ID']" />
                </TrackID>
            </Track>
        </xsl:for-each>

        <xsl:for-each select="//dict[preceding-sibling::*[1]='Upload Information']">
            <Description>
                <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Playlist Description']" />
            </Description>
            <Title>
                <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Playlist Title']" />
            </Title>
            <Username>
                <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Username']" />
            </Username>
        </xsl:for-each>
    </playlist>
</xsl:template>    

这是生成的XML:

<?xml version="1.0" encoding="UTF-8"?>
<playlist>
   <Track>
      <Artist>The Arcade Fire</Artist>
      <Album>Funeral</Album>
      <TrackID>0</TrackID>
   </Track>
   <Track>
      <Artist>Burial</Artist>
      <Album>Untrue</Album>
      <TrackID>1</TrackID>
   </Track>
   <Description>My description</Description>
   <Title>Mytitle</Title>
   <Username>Maven</Username>
</playlist>

答案 1 :(得分:0)

您可能对此替代转换感兴趣,该转换使用模板而不是for-each元素。

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

  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <playlist>
      <xsl:apply-templates select="plist/dict/dict[preceding-sibling::key = 'Tracks']/dict" mode="track"/>
      <xsl:apply-templates select="plist/dict/dict[preceding-sibling::key = 'Upload Information']" mode="info"/>
    </playlist>
  </xsl:template>

  <xsl:template match="dict" mode="track">
    <track>
      <Artist>
        <xsl:value-of select="string[preceding-sibling::key = 'Artist']"/>
      </Artist>
      <Album>
        <xsl:value-of select="string[preceding-sibling::key = 'Album']"/>
      </Album>
      <TrackID>
        <xsl:value-of select="string[preceding-sibling::key = 'Track ID']"/>
      </TrackID>
    </track>
  </xsl:template>

  <xsl:template match="dict" mode="info">
    <info>
      <Description>
        <xsl:value-of select="string[preceding-sibling::key = 'Playlist Description']"/>
      </Description>
      <Title>
        <xsl:value-of select="string[preceding-sibling::key = 'Playlist Title']"/>
      </Title>
      <Username>
        <xsl:value-of select="string[preceding-sibling::key = 'Username']"/>
      </Username>
    </info>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<?xml version="1.0" encoding="utf-8"?>
<playlist>
   <track>
      <Artist>The Arcade Fire</Artist>
      <Album>Funeral</Album>
      <TrackID>0</TrackID>
   </track>
   <track>
      <Artist>Burial</Artist>
      <Album>Untrue</Album>
      <TrackID>1</TrackID>
   </track>
   <info>
      <Description>My description</Description>
      <Title>Mytitle</Title>
      <Username>Maven</Username>
   </info>
</playlist>