从TXT文件生成XML格式

从TXT文件生成XML格式,xml,awk,data-conversion,Xml,Awk,Data Conversion,我有下面的输入txt文件,我正在尝试生成下面的XMl文件。我试着用awk来做,但是 我想我正在重新发明轮子。你建议我怎么做?谢谢 输入txt文件(示例,此输入可能更大) 所需的xml文件 <?xml version="1.0" encoding="utf-8"?> <XMLRT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SomeSchema.xsd"

我有下面的输入txt文件,我正在尝试生成下面的XMl文件。我试着用awk来做,但是 我想我正在重新发明轮子。你建议我怎么做?谢谢

输入txt文件(示例,此输入可能更大)

所需的xml文件

<?xml version="1.0" encoding="utf-8"?>

<XMLRT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SomeSchema.xsd" bename="The name" status="v" version="1.4" revision="1" type="x-rt">
<INTRO>
    <title>Some title</title>
    <creator>
    </creator>
    <subject>Some subject</subject>
    <description>Some description</description>
    <date>2010-05-12</date>
    <type>Some text</type>
</INTRO>
<RTBLOCK bname="Usw" bnumber="1" bsname="1U">
    <CTR cnumber="1">
    <ES vnumber="1">Desktop</ES>
    <ES vnumber="2">Netbooks</ES>
    <ES vnumber="3">SerES, mainframes and supercomputers</ES>
    <ES vnumber="4">Smart devices</ES>
    <ES vnumber="5">Embedded devices</ES>
    <ES vnumber="6">Gaming</ES>
    <ES vnumber="7">Specialized uses</ES>
    </CTR>
    <CTR cnumber="2">
    <ES vnumber="1">Precursors</ES>
    <ES vnumber="2">Creation</ES>
    <ES vnumber="5">Naming</ES>
    <ES vnumber="6">Commercial and popular uptake</ES>
    <ES vnumber="9">Current development</ES>
    </CTR>
</RTBLOCK>
<RTBLOCK bname="Des" bnumber="1" bsname="1D">
    <CTR cnumber="1">
    <ES vnumber="1">User interface</ES>
    <ES vnumber="2">Video input infrastructure</ES>
    <ES vnumber="3">Hardware</ES>
    </CTR>
    <CTR cnumber="2">
    <ES vnumber="1">Community</ES>
    <ES vnumber="2">Programming on Linux</ES>
    </CTR>
</RTBLOCK>
</XMLRT>

一些头衔
某个主题
一些描述
2010-05-12
一些文本
桌面
笔电
系列、大型机和超级计算机
智能设备
嵌入式设备
游戏
专门用途
先兆
创造
命名
商业和大众接受
当前发展
用户界面
视频输入基础设施
硬件
社区
在Linux上编程

只是为了说明您不需要一个支持XML的工具来为任何给定目的生成所需的特定XML,以下是一种方法:

$ cat tst.awk
BEGIN {
    print    "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
    print    ""
    print    "<XMLRT xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"SomeSchema.xsd\" bename=\"The name\" status=\"v\" version=\"1.4\" revision=\"1\" type=\"x-rt\">"
    print    "<INTRO>"
    print    "    <title>Some title</title>"
    print    "    <creator>"
    print    "    </creator>"
    print    "    <subject>Some subject</subject>"
    print    "    <description>Some description</description>"
    print    "    <date>2010-05-12</date>"
    print    "    <type>Some text</type>"
    print    "</INTRO>"

    rtBeg  = "<RTBLOCK bname=\"%s\" bnumber=\"1\" bsname=\"1%s\">\n"
    ctrBeg = "    <CTR cnumber=\"%d\">\n"
    esBody = "    <ES vnumber=\"%d\">%s</ES>\n"
    ctrEnd = "    </CTR>\n"
    rtEnd  = "</RTBLOCK>\n"
    xmlEnd = "</XMLRT>\n"
}
{
    bname = $1

    split($2,tmp,/:/)
    cnum = tmp[1]
    vnum = tmp[2]

    text = $0
    sub(/([^[:space:]]+[[:space:]]+){2}/,"",text)
}

bname != prevBname {
    if (prevCnum  != "") printf ctrEnd
    if (prevBname != "") printf rtEnd
    printf rtBeg, bname, substr(bname,1,1)
    prevCnum = ""
    prevBname = bname
}

cnum != prevCnum {
    if (prevCnum != "") printf ctrEnd
    printf ctrBeg, cnum
    prevCnum = cnum
}

{ printf esBody, vnum, text }

END {
    if (prevCnum  != "") printf ctrEnd
    if (prevBname != "") printf rtEnd
    printf xmlEnd
}
$cat tst.awk
开始{
打印“”
打印“”
打印“”
打印“”
打印“一些标题”
打印“”
打印“”
打印“某个主题”
打印“一些描述”
打印“2010-05-12”
打印“一些文本”
打印“”
rtBeg=“\n”
ctrBeg=“\n”
esBody=“%s\n”
ctrEnd=“\n”
rtEnd=“\n”
xmlEnd=“\n”
}
{
bname=$1
拆分($2,tmp,/:/)
cnum=tmp[1]
vnum=tmp[2]
text=$0
sub(/([^[:space:]+[:space:]+){2}/,“”,text)
}
bname!=prevBname{
如果(上一个!=“”)打印ctrEnd
如果(prevBname!=“”)printf rtEnd
printf rtBeg,bname,substr(bname,1,1)
prevCnum=“”
prevBname=bname
}
cnum!=前鼻孔{
如果(上一个!=“”)打印ctrEnd
中央大学印刷厂
前cnum=cnum
}
{printf esBody,vnum,text}
结束{
如果(上一个!=“”)打印ctrEnd
如果(prevBname!=“”)printf rtEnd
printfxmlend
}

$awk-f tst.awk文件
一些头衔
某个主题
一些描述
2010-05-12
一些文本
桌面
笔电
服务器、大型机和超级计算机
智能设备
嵌入式设备
游戏
专门用途
先兆
创造
命名
商业和大众接受
当前发展
用户界面
视频输入基础设施
硬件
社区
在Linux上编程
在任何UNIX设备上的任何shell中的任何POSIX awk中,上述功能都将高效、健壮且可移植

你建议我怎么做

我建议使用XSLT-2.0+处理器来输出想要的XML文件。但其他XSLT-2.0处理器也可以工作

以下XSLT-2.0样式表分两步工作:

  • 将未分析的文本检索到
  • 使用正则表达式通过
  • 使用
  • 因此样式表可以如下所示:

    <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
        <xsl:output method="xml" />    
        <xsl:param name="text-encoding" as="xs:string" select="'utf-8'"/>
        <xsl:param name="text-uri"      as="xs:string" select="'file:///home/kubuntu/Downloads/input.txt'"/>
    
        <xsl:template match="/">
            <XMLRT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SomeSchema.xsd" bename="The name" status="v" version="1.4" revision="1" type="x-rt">
                <!-- Step 1 ### get unparsed text -->
                <xsl:variable name="input-text" select="unparsed-text($text-uri, $text-encoding)"/>
                <!-- Step 2 ### Apply RegEx to every line to create <Line...> elements -->
                <xsl:variable name="xmlStepOne">
                    <xsl:for-each select="tokenize($input-text,'&#xa;')">
                        <xsl:if test=".!=''">                  <!-- Skip empty lines -->
                            <xsl:analyze-string select="." regex="([^\s]+)\s([^:]+):([^\s]+)\s(.*)$">
                                <xsl:matching-substring>       <!-- Parse line with RegEx and create <Line...> XML -->
                                    <Line str="{regex-group(1)}" idx1="{regex-group(2)}" idx2="{regex-group(3)}"><xsl:value-of select="regex-group(4)"/></Line>
                                </xsl:matching-substring>
                                <xsl:non-matching-substring>   <!-- Output an error if a line cannot be processed -->
                                    <xsl:message terminate="yes">Error processing line &#xa;<xsl:value-of select="current()"/>&#xa;</xsl:message>
                                </xsl:non-matching-substring>
                            </xsl:analyze-string>                
                        </xsl:if>
                    </xsl:for-each>
                </xsl:variable>
                <!-- Step 3 ### Group the linear flow of <Line...> elements -->
                <xsl:for-each-group select="$xmlStepOne/Line" group-by="@str">
                    <RTBLOCK bname="{current-grouping-key()}" bnumber="1" bsname="{concat('1',substring(current-grouping-key(),1,1))}">
                        <xsl:for-each-group select="current-group()" group-by="@idx1">
                            <xsl:sort select="@idx1" />
                            <CTR cnumber="{@idx1}"> 
                                <xsl:for-each select="current-group()">
                                    <xsl:sort select="@idx2" />
                                    <ES vnumber="{@idx2}"><xsl:value-of select="."/></ES>
                                </xsl:for-each>
                            </CTR>
                        </xsl:for-each-group>
                    </RTBLOCK>
                </xsl:for-each-group>
            </XMLRT>
        </xsl:template>
    
    </xsl:stylesheet>
    
    
    错误处理线
    
    ;
    
    您可以在开始时使用这两个参数设置输入文件名和编码

    上述示例文件的输出为:

    <?xml version="1.0" encoding="UTF-8"?>
    <XMLRT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SomeSchema.xsd" bename="The name" status="v" version="1.4" revision="1" type="x-rt">
        <RTBLOCK bname="Usw" bnumber="1" bsname="1U">
            <CTR cnumber="1">
                <ES vnumber="1">Desktop</ES>
                <ES vnumber="2">Netbooks</ES>
                <ES vnumber="3">Servers, mainframes and supercomputers</ES>
                <ES vnumber="4">Smart devices</ES>
                <ES vnumber="5">Embedded devices</ES>
                <ES vnumber="6">Gaming</ES>
                <ES vnumber="7">Specialized uses</ES>
            </CTR>
            <CTR cnumber="2">
                <ES vnumber="1">Precursors</ES>
                <ES vnumber="2">Creation</ES>
                <ES vnumber="5">Naming</ES>
                <ES vnumber="6">Commercial and popular uptake</ES>
                <ES vnumber="9">Current development</ES>
            </CTR>
        </RTBLOCK>
        <RTBLOCK bname="Des" bnumber="1" bsname="1D">
            <CTR cnumber="1">
                <ES vnumber="1">User interface</ES>
                <ES vnumber="2">Video input infrastructure</ES>
                <ES vnumber="3">Hardware</ES>
            </CTR>
            <CTR cnumber="2">
                <ES vnumber="1">Community</ES>
                <ES vnumber="2">Programming on Linux</ES>
            </CTR>
        </RTBLOCK>
    </XMLRT>
    
    
    桌面
    笔电
    服务器、大型机和超级计算机
    智能设备
    嵌入式设备
    游戏
    专门用途
    先兆
    创造
    命名
    商业和大众接受
    当前发展
    用户界面
    视频输入基础设施
    硬件
    社区
    在Linux上编程
    

    这种方法的另一个优点是,您可以使用XML/XSLT处理所有内容,因此它可以了解字符编码和其他所有使用
    awk
    或类似工具的更简单解决方案未涉及的内容。

    请不要在此处发布工作请求。以目前的形式,这篇文章不是一个问题,而是一个任务分配。至少,发布您当前的代码,并描述您的困境。尽管如此,对于这个任务来说,awk是一个糟糕的工具选择。使用支持XML的工具。例如,Python解析文本文件,lxml模块生成XML树。谢谢Tomalak的回答。实际上我不是学生,这不是任务分配。我有这类文件,正在寻求帮助以选择更好的工具。我认为AWK是一个不好的选择,但我使用它是因为这是我知道一点的工具。我所说的“任务分配”是指:你试图分配任务给我们。“我有X,我需要Y”不是问题。这是老板给员工的,而不是堆栈溢出的工作方式。此外,“我想继续使用错误的工具,因为我知道它一点”不是一个好借口。了解如何使用正确的工具。对于包含
    &
    中任何一种的数据,中断。此外,这也保证了输出实际上是UTF-8编码的(使用任何P
    <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
        <xsl:output method="xml" />    
        <xsl:param name="text-encoding" as="xs:string" select="'utf-8'"/>
        <xsl:param name="text-uri"      as="xs:string" select="'file:///home/kubuntu/Downloads/input.txt'"/>
    
        <xsl:template match="/">
            <XMLRT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SomeSchema.xsd" bename="The name" status="v" version="1.4" revision="1" type="x-rt">
                <!-- Step 1 ### get unparsed text -->
                <xsl:variable name="input-text" select="unparsed-text($text-uri, $text-encoding)"/>
                <!-- Step 2 ### Apply RegEx to every line to create <Line...> elements -->
                <xsl:variable name="xmlStepOne">
                    <xsl:for-each select="tokenize($input-text,'&#xa;')">
                        <xsl:if test=".!=''">                  <!-- Skip empty lines -->
                            <xsl:analyze-string select="." regex="([^\s]+)\s([^:]+):([^\s]+)\s(.*)$">
                                <xsl:matching-substring>       <!-- Parse line with RegEx and create <Line...> XML -->
                                    <Line str="{regex-group(1)}" idx1="{regex-group(2)}" idx2="{regex-group(3)}"><xsl:value-of select="regex-group(4)"/></Line>
                                </xsl:matching-substring>
                                <xsl:non-matching-substring>   <!-- Output an error if a line cannot be processed -->
                                    <xsl:message terminate="yes">Error processing line &#xa;<xsl:value-of select="current()"/>&#xa;</xsl:message>
                                </xsl:non-matching-substring>
                            </xsl:analyze-string>                
                        </xsl:if>
                    </xsl:for-each>
                </xsl:variable>
                <!-- Step 3 ### Group the linear flow of <Line...> elements -->
                <xsl:for-each-group select="$xmlStepOne/Line" group-by="@str">
                    <RTBLOCK bname="{current-grouping-key()}" bnumber="1" bsname="{concat('1',substring(current-grouping-key(),1,1))}">
                        <xsl:for-each-group select="current-group()" group-by="@idx1">
                            <xsl:sort select="@idx1" />
                            <CTR cnumber="{@idx1}"> 
                                <xsl:for-each select="current-group()">
                                    <xsl:sort select="@idx2" />
                                    <ES vnumber="{@idx2}"><xsl:value-of select="."/></ES>
                                </xsl:for-each>
                            </CTR>
                        </xsl:for-each-group>
                    </RTBLOCK>
                </xsl:for-each-group>
            </XMLRT>
        </xsl:template>
    
    </xsl:stylesheet>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <XMLRT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SomeSchema.xsd" bename="The name" status="v" version="1.4" revision="1" type="x-rt">
        <RTBLOCK bname="Usw" bnumber="1" bsname="1U">
            <CTR cnumber="1">
                <ES vnumber="1">Desktop</ES>
                <ES vnumber="2">Netbooks</ES>
                <ES vnumber="3">Servers, mainframes and supercomputers</ES>
                <ES vnumber="4">Smart devices</ES>
                <ES vnumber="5">Embedded devices</ES>
                <ES vnumber="6">Gaming</ES>
                <ES vnumber="7">Specialized uses</ES>
            </CTR>
            <CTR cnumber="2">
                <ES vnumber="1">Precursors</ES>
                <ES vnumber="2">Creation</ES>
                <ES vnumber="5">Naming</ES>
                <ES vnumber="6">Commercial and popular uptake</ES>
                <ES vnumber="9">Current development</ES>
            </CTR>
        </RTBLOCK>
        <RTBLOCK bname="Des" bnumber="1" bsname="1D">
            <CTR cnumber="1">
                <ES vnumber="1">User interface</ES>
                <ES vnumber="2">Video input infrastructure</ES>
                <ES vnumber="3">Hardware</ES>
            </CTR>
            <CTR cnumber="2">
                <ES vnumber="1">Community</ES>
                <ES vnumber="2">Programming on Linux</ES>
            </CTR>
        </RTBLOCK>
    </XMLRT>