0

我有这样的代码

<Library>
    <Books>
        <Book>
            <ISBN>123</ISBN>
            <Name>Book 1</Name>
            <Author-Ref>/Library/Authors/Author[2]</Author-Ref>
        </Book>
        <Book>
            <ISBN>425</ISBN>
            <Name>Book 2</Name>
            <Author-Ref>/Library/Authors/Author[1]</Author-Ref>
        </Book>     
    </Books>
    <Authors>
        <Author>
            <Name>John smith</Name>
            <Nationality>American</Nationality>
            <BirthDate>08051977</BirthDate>
        </Author>
        <Author>
            <Name>Sandra Johns</Name>
            <Nationality>American</Nationality>
            <BirthDate>03091981</BirthDate>
        </Author>       
    </Authors>
</Library>

我想写 xslt 代码,打印书名,作者姓名。

如何使用 XSLT 解析对 Auther 名称的引用?

<xsl:for-each select="/Library/Books/Book">
    Book Name: <xsl:value-of select="./Name"/>
    Auther Name: ?????
</xsl:for-each>
4

3 回答 3

1

我会分两个阶段进行;第一阶段是添加Author元素的路径。第二阶段使用添加的路径来产生所需的输出。

这可以在单个 XSLT (2.0) 中通过将新输入和路径添加到变量中来完成,但这会导致较大文档的内存问题。

XML 输入(input.xml)

<Library>
    <Books>
        <Book>
            <ISBN>123</ISBN>
            <Name>Book 1</Name>
            <Author-Ref>/Library/Authors/Author[2]</Author-Ref>
        </Book>
        <Book>
            <ISBN>425</ISBN>
            <Name>Book 2</Name>
            <Author-Ref>/Library/Authors/Author[1]</Author-Ref>
        </Book>     
    </Books>
    <Authors>
        <Author>
            <Name>John smith</Name>
            <Nationality>American</Nationality>
            <BirthDate>08051977</BirthDate>
        </Author>
        <Author>
            <Name>Sandra Johns</Name>
            <Nationality>American</Nationality>
            <BirthDate>03091981</BirthDate>
        </Author>       
    </Authors>
</Library>

第一个 XSLT (pass1.xsl)

这会将属性添加pathAuthor元素中。

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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:if test="self::Author">
                <xsl:attribute name="path">
                    <xsl:for-each select="ancestor-or-self::*">
                        <xsl:value-of select="concat('/',local-name())"/>
                        <xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
                            <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>                      
                        </xsl:if>
                    </xsl:for-each>
                </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML 输出(temp.xml)

@path已添加通知。

<Library>
   <Books>
      <Book>
         <ISBN>123</ISBN>
         <Name>Book 1</Name>
         <Author-Ref>/Library/Authors/Author[2]</Author-Ref>
      </Book>
      <Book>
         <ISBN>425</ISBN>
         <Name>Book 2</Name>
         <Author-Ref>/Library/Authors/Author[1]</Author-Ref>
      </Book>
   </Books>
   <Authors>
      <Author path="/Library/Authors/Author[1]">
         <Name>John smith</Name>
         <Nationality>American</Nationality>
         <BirthDate>08051977</BirthDate>
      </Author>
      <Author path="/Library/Authors/Author[2]">
         <Name>Sandra Johns</Name>
         <Nationality>American</Nationality>
         <BirthDate>03091981</BirthDate>
      </Author>
   </Authors>
</Library>

第二个 XSLT (pass2.xsl)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*/Books/Book">
        <xsl:value-of select="concat('Book Name: ',Name,'&#xA;')"/>
        <xsl:value-of select="concat('Author Name: ',
        /*/Authors/Author[@path=current()/Author-Ref]/Name,'&#xA;')"/>
    </xsl:template>

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

</xsl:stylesheet>

最终输出

Book Name: Book 1
Author Name: Sandra Johns
Book Name: Book 2
Author Name: John smith
于 2013-07-11T19:26:49.870 回答
0

这是一个 XSLT 1.0 样式表

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

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:for-each select="/Library/Books/Book">
            <xsl:text>Book Name: </xsl:text>
            <xsl:value-of select="./Name"/>
            <xsl:text>&#x000A;</xsl:text>
            <xsl:text>Auther Name: </xsl:text>
            <xsl:value-of select="dyn:evaluate(Author-Ref)/Name"/>
            <xsl:text>&#x000A;</xsl:text>                
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

使用 Xalan 和 Xsltproc 进行测试,以使用提供的输入生成此输出:

Book Name: Book 1
Auther Name: Sandra Johns
Book Name: Book 2
Auther Name: John smith

请注意,您需要为您的处理器提供 EXSLT 模块。我不是 Xalan 用户,但基于这个答案,也有一个xalan:evaluate。如果您使用的是 Saxon,则可以使用

xmlns:saxon="http://saxon.sf.net/"
extension-element-prefixes="saxon"

<xsl:value-of select="saxon:evaluate(Author-Ref)/Name"/>
于 2013-07-13T01:28:44.013 回答
0

One way is to mix a bit of unix shell script with the xmlstarlet tool. The xmlstarlet command that serves input to the while loop

xmlstarlet sel -T -t \
    -m "/Library/Books/Book" \
    -v "concat( Name, '>', Author-Ref )" \
    -n \
xmlfile

searches for the Name and the Author-Ref content and prints both separated with character >. It would fail if either of both fields contains that character.

Book 1>/Library/Authors/Author[2]
Book 2>/Library/Authors/Author[1]

Inside the loop print the name and execute a second xmlstarlet command with the xpath of author_ref to extract the author name.

The complete command:

while IFS=">" read -r name author_ref; do
    printf "Book name: %s\n" "$name"
    printf "Author Name: %s\n" "$(xmlstarlet sel -T -t -v "${author_ref}/Name" xmlfile)"
done < <(xmlstarlet sel -T -t -m "/Library/Books/Book" -v "concat( Name, '>', Author-Ref )" -n xmlfile)

That yields:

Book name: Book 1
Author Name: Sandra Johns
Book name: Book 2
Author Name: John smith
于 2013-07-11T21:58:49.170 回答